Thrift-2421:Tree/Recursive struct support in thrift
Client: compiler
Patch: Dave Watson
Patch to go along with pull request 84 to fix missing destructors.
Github Pull Request: This closes #98
----
commit f4daec9b0af386e8f6e9e66fb688aab8cd949fdc
Date: 2014-04-09T17:33:18Z
Also generate destructor for _result, presult, args, pargs
diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc
index f6cee8d..c9a44ef 100755
--- a/compiler/cpp/src/generate/t_cpp_generator.cc
+++ b/compiler/cpp/src/generate/t_cpp_generator.cc
@@ -119,7 +119,7 @@
bool read=true,
bool write=true,
bool swap=false);
- void generate_struct_definition (std::ofstream& out, t_struct* tstruct);
+ void generate_struct_definition (std::ofstream& out, t_struct* tstruct, bool setters=true);
void generate_copy_constructor (std::ofstream& out, t_struct* tstruct);
void generate_assignment_operator (std::ofstream& out, t_struct* tstruct);
void generate_struct_fingerprint (std::ofstream& out, t_struct* tstruct, bool is_definition);
@@ -1137,7 +1137,8 @@
}
void t_cpp_generator::generate_struct_definition(ofstream& out,
- t_struct* tstruct) {
+ t_struct* tstruct,
+ bool setters) {
// Get members
vector<t_field*>::const_iterator m_iter;
const vector<t_field*>& members = tstruct->get_members();
@@ -1162,35 +1163,37 @@
}
// Create a setter function for each field
- for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
- 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();
- if (is_reference((*m_iter))) {
- std::string type = type_name((*m_iter)->get_type());
- indent(out) << "if (" << (*m_iter)->get_name() << ") {" << endl;
- indent(out) << " *" << (*m_iter)->get_name() << " = val;" << endl;
- indent(out) << "} else {" << endl;
- indent(out) << " " << (*m_iter)->get_name() << " = new " << type << "(val);" << endl;
- indent(out) << "}" << endl;
- } else {
- out << indent() << (*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) {
+ if (setters) {
+ for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
out <<
- indent() <<
- indent() << "__isset." << (*m_iter)->get_name() << " = true;" << endl;
+ endl <<
+ indent() << "void " << tstruct->get_name() << "::__set_" << (*m_iter)->get_name() <<
+ "(" << type_name((*m_iter)->get_type(), false, true);
+ out << " val) {" << endl;
+ indent_up();
+ if (is_reference((*m_iter))) {
+ std::string type = type_name((*m_iter)->get_type());
+ indent(out) << "if (" << (*m_iter)->get_name() << ") {" << endl;
+ indent(out) << " *" << (*m_iter)->get_name() << " = val;" << endl;
+ indent(out) << "} else {" << endl;
+ indent(out) << " " << (*m_iter)->get_name() << " = new " << type << "(val);" << endl;
+ indent(out) << "}" << endl;
+ } else {
+ out << indent() << (*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;
}
- out <<
- indent()<< "}" << endl;
}
out << endl;
}
@@ -1887,10 +1890,12 @@
// 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, 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, ts, false);
generate_struct_writer(out, ts, true);
ts->set_name(name_orig);
@@ -3342,11 +3347,13 @@
}
generate_struct_declaration(f_header_, &result, false);
+ generate_struct_definition(out, &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, &result, false);
generate_struct_reader(out, &result, true);
if (gen_cob_style_) {
generate_struct_writer(out, &result, true);
diff --git a/lib/cpp/test/RecursiveTest b/lib/cpp/test/RecursiveTest
deleted file mode 100755
index 7e67179..0000000
--- a/lib/cpp/test/RecursiveTest
+++ /dev/null
@@ -1,245 +0,0 @@
-#! /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.
-#
-# RecursiveTest - temporary wrapper script for .libs/RecursiveTest
-# Generated by libtool (GNU libtool) 2.4.2 Debian-2.4.2-1ubuntu1
-#
-# The RecursiveTest 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='s/\([`"$\\]\)/\\\1/g'
-
-# 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="(cd /thrift/lib/cpp/test; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games; export PATH; g++ -Wall -g -O2 -o \$progdir/\$file RecursiveTest.o -L/usr/lib ./.libs/libtestgencpp.a /thrift/lib/cpp/.libs/libthrift.so -lssl -lcrypto -lrt -lpthread -Wl,-rpath -Wl,/thrift/lib/cpp/.libs)"
-
-# This environment variable determines our operation mode.
-if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then
- # install mode needs the following variables:
- generated_by_libtool_version='2.4.2'
- notinst_deplibs=' /thrift/lib/cpp/libthrift.la'
-else
- # When we are sourced in execute mode, $file and $ECHO are already set.
- if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
- file="$0"
-
-# A function that is used when there is no print builtin or printf.
-func_fallback_echo ()
-{
- eval 'cat <<_LTECHO_EOF
-$1
-_LTECHO_EOF'
-}
- ECHO="printf %s\\n"
- 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/ which is used only on
-# windows platforms, and (c) all begin with the string --lt-
-# (application programs are unlikely to have options which 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 ../../../libtool value, followed by no.
-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" | /bin/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" | /bin/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 "RecursiveTest:RecursiveTest:${LINENO}: libtool wrapper (GNU libtool) 2.4.2 Debian-2.4.2-1ubuntu1" 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 "RecursiveTest:RecursiveTest:${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 ()
-{
-
- if test -n "$lt_option_debug"; then
- $ECHO "RecursiveTest:RecursiveTest:${LINENO}: newargv[0]: $progdir/$program" 1>&2
- func_lt_dump_args ${1+"$@"} 1>&2
- fi
- exec "$progdir/$program" ${1+"$@"}
-
- $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" | /bin/sed 's%/[^/]*$%%'`
- test "x$thisdir" = "x$file" && thisdir=.
-
- # Follow symbolic links until we get to the real thisdir.
- file=`ls -ld "$file" | /bin/sed -n 's/.*-> //p'`
- while test -n "$file"; do
- destdir=`$ECHO "$file" | /bin/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" | /bin/sed 's%^.*/%%'`
- file=`ls -ld "$thisdir/$file" | /bin/sed -n 's/.*-> //p'`
- done
-
- # Usually 'no', except on cygwin/mingw when embedded into
- # the cwrapper.
- WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no
- 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
- *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /bin/sed 's%[\\/][^\\/]*$%%'` ;;
- .libs ) thisdir=. ;;
- esac
- fi
-
- # Try to get the absolute directory name.
- absdir=`cd "$thisdir" && pwd`
- test -n "$absdir" && thisdir="$absdir"
-
- program=lt-'RecursiveTest'
- progdir="$thisdir/.libs"
-
- if test ! -f "$progdir/$program" ||
- { file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | /bin/sed 1q`; \
- test "X$file" != "X$progdir/$program"; }; then
-
- file="$$-$program"
-
- if test ! -d "$progdir"; then
- mkdir "$progdir"
- else
- rm -f "$progdir/$file"
- fi
-
- # relink executable if necessary
- if test -n "$relink_command"; then
- if relink_command_output=`eval $relink_command 2>&1`; then :
- else
- printf %s\n "$relink_command_output" >&2
- rm -f "$progdir/$file"
- exit 1
- fi
- fi
-
- mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null ||
- { rm -f "$progdir/$program";
- mv -f "$progdir/$file" "$progdir/$program"; }
- rm -f "$progdir/$file"
- fi
-
- if test -f "$progdir/$program"; then
- if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; 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 libtool documentation for more information." 1>&2
- exit 1
- fi
-fi