src/parse/t_enum.h \
src/parse/t_enum_value.h \
src/parse/t_typedef.h \
+ src/parse/t_typedef.cc \
src/parse/t_container.h \
src/parse/t_list.h \
src/parse/t_set.h \
void generate_typedef(t_typedef* ttypedef);
void generate_enum(t_enum* tenum);
+ void generate_forward_declaration(t_struct* tstruct);
void generate_struct(t_struct* tstruct) {
generate_cpp_struct(tstruct, false);
}
void print_const_value(std::ofstream& out, std::string name, t_type* type, t_const_value* value);
std::string render_const_value(std::ofstream& out, std::string name, t_type* type, t_const_value* value);
- void generate_struct_definition (std::ofstream& out, t_struct* tstruct,
+ void generate_struct_declaration (std::ofstream& out, t_struct* tstruct,
bool is_exception=false,
bool pointers=false,
bool read=true,
bool write=true,
bool swap=false);
+ void generate_struct_definition (std::ofstream& out, t_struct* tstruct);
+ 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);
void generate_struct_reader (std::ofstream& out, t_struct* tstruct, bool pointers=false);
void generate_struct_writer (std::ofstream& out, t_struct* tstruct, bool pointers=false);
void generate_deserialize_struct (std::ofstream& out,
t_struct* tstruct,
- std::string prefix="");
-
+ std::string prefix="",
+ bool pointer=false);
+
void generate_deserialize_container (std::ofstream& out,
t_type* ttype,
std::string prefix="");
void generate_serialize_struct (std::ofstream& out,
t_struct* tstruct,
- std::string prefix="");
+ std::string prefix="",
+ bool pointer=false);
void generate_serialize_container (std::ofstream& out,
t_type* ttype,
void generate_local_reflection(std::ofstream& out, t_type* ttype, bool is_definition);
void generate_local_reflection_pointer(std::ofstream& out, t_type* ttype);
+ bool is_reference(t_field* tfield) {
+ return tfield->annotations_.count("cpp.ref") != 0;
+ }
+
bool is_complex_type(t_type* ttype) {
ttype = get_true_type(ttype);
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
* @param tstruct The struct definition
*/
void t_cpp_generator::generate_cpp_struct(t_struct* tstruct, bool is_exception) {
- generate_struct_definition(f_types_, tstruct, is_exception,
+ generate_struct_declaration(f_types_, tstruct, is_exception,
false, true, true, true);
+ generate_struct_definition(f_types_impl_, tstruct);
generate_struct_fingerprint(f_types_impl_, tstruct, true);
generate_local_reflection(f_types_, tstruct, false);
generate_local_reflection(f_types_impl_, tstruct, true);
generate_struct_reader(out, tstruct);
generate_struct_writer(out, tstruct);
generate_struct_swap(f_types_impl_, tstruct);
+ generate_copy_constructor(f_types_impl_, tstruct);
+ generate_assignment_operator(f_types_impl_, tstruct);
+}
+
+void t_cpp_generator::generate_copy_constructor(
+ ofstream& out,
+ t_struct* tstruct) {
+ std::string tmp_name = tmp("other");
+
+ indent(out) << tstruct->get_name() << "::" <<
+ tstruct->get_name() << "(const " << tstruct->get_name() <<
+ "& " << tmp_name << ") {" << endl;
+ indent_up();
+
+ const vector<t_field*>& members = tstruct->get_members();
+ vector<t_field*>::const_iterator f_iter;
+ for (f_iter = members.begin(); f_iter != members.end(); ++f_iter) {
+ if (is_reference(*f_iter)) {
+ std::string type = type_name((*f_iter)->get_type());
+ indent(out) << (*f_iter)->get_name() << " = new " << type << "(*" << tmp_name << "." <<
+ (*f_iter)->get_name() << ");" << endl;
+ } else {
+ indent(out) << (*f_iter)->get_name() << " = " << tmp_name << "." <<
+ (*f_iter)->get_name() << ";" << endl;
+ }
+ }
+
+ indent_down();
+ indent(out) << "}" << endl;
+}
+
+void t_cpp_generator::generate_assignment_operator(
+ ofstream& out,
+ t_struct* tstruct) {
+ std::string tmp_name = tmp("other");
+
+ indent(out) << tstruct->get_name() << "& " << tstruct->get_name() << "::"
+ "operator=(const " << tstruct->get_name() <<
+ "& " << tmp_name << ") {" << endl;
+ indent_up();
+
+ const vector<t_field*>& members = tstruct->get_members();
+ vector<t_field*>::const_iterator f_iter;
+ for (f_iter = members.begin(); f_iter != members.end(); ++f_iter) {
+ if (is_reference(*f_iter)) {
+ std::string type = type_name((*f_iter)->get_type());
+ indent(out) << "if (this == &" << tmp_name << ") return *this;" << endl;
+ indent(out) << "if (" << (*f_iter)->get_name() << ") {" << endl;
+ indent(out) << " *" << (*f_iter)->get_name() << " = *" << tmp_name << "." <<
+ (*f_iter)->get_name() << ";" << endl;
+ indent(out) << "} else {" << endl;
+ indent(out) << " " << (*f_iter)->get_name() << " = new " << type << "(*" << tmp_name << "." <<
+ (*f_iter)->get_name() << ");" << endl;
+ indent(out) << "}" << endl;
+ } else {
+ indent(out) << (*f_iter)->get_name() << " = " << tmp_name << "." <<
+ (*f_iter)->get_name() << ";" << endl;
+ }
+ }
+
+ indent(out) << "return *this;" << endl;
+ indent_down();
+ indent(out) << "}" << endl;
}
/**
* @param out Output stream
* @param tstruct The struct
*/
-void t_cpp_generator::generate_struct_definition(ofstream& out,
+void t_cpp_generator::generate_struct_declaration(ofstream& out,
t_struct* tstruct,
bool is_exception,
bool pointers,
generate_struct_fingerprint(out, tstruct, false);
if (!pointers) {
+ // Copy constructor
+ indent(out) <<
+ tstruct->get_name() << "(const " << tstruct->get_name() << "&);" << endl;
+
+ // Assignment Operator
+ indent(out) << tstruct->get_name() << "& operator=(const " << tstruct->get_name() << "&);" << endl;
+
// Default constructor
indent(out) <<
tstruct->get_name() << "()";
+
bool init_ctor = false;
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()) {
+ if (t->is_base_type() || t->is_enum() || is_reference(*m_iter)) {
string dval;
if (t->is_enum()) {
dval += "(" + type_name(t) + ")";
} else {
out << ", " << (*m_iter)->get_name() << "(" << dval << ")";
}
- }
+ }
}
out << " {" << endl;
indent_up();
if (tstruct->annotations_.find("final") == tstruct->annotations_.end()) {
out <<
endl <<
- indent() << "virtual ~" << tstruct->get_name() << "() throw() {}" << endl << endl;
+ indent() << "virtual ~" << tstruct->get_name() << "() throw();" << endl;
}
// Pointer to this structure's reflection local typespec.
// Declare all fields
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
indent(out) <<
- declare_field(*m_iter, false, pointers && !(*m_iter)->get_type()->is_xception(), !read) << endl;
+ declare_field(*m_iter, false, (pointers && !(*m_iter)->get_type()->is_xception()) || is_reference(*m_iter), !read) << endl;
}
// Add the __isset data member if we need it, using the definition from above
endl <<
indent() << "void __set_" << (*m_iter)->get_name() <<
"(" << type_name((*m_iter)->get_type(), false, true);
- out << " val) {" << endl << indent() <<
- indent() << (*m_iter)->get_name() << " = val;" << endl;
-
- // 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 << " val);" << endl;
}
out << endl;
}
}
+void t_cpp_generator::generate_struct_definition(ofstream& out,
+ t_struct* tstruct) {
+ // Get members
+ vector<t_field*>::const_iterator m_iter;
+ const vector<t_field*>& members = tstruct->get_members();
+
+
+ // Destructor
+ if (tstruct->annotations_.find("final") == tstruct->annotations_.end()) {
+ out <<
+ endl <<
+ indent() << tstruct->get_name() << "::~" << tstruct->get_name() << "() throw() {" << endl;
+ indent_up();
+
+ for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+ if (is_reference(*m_iter)) {
+ out << indent() <<
+ "delete " << (*m_iter)->get_name() << ";" << endl;
+ }
+ }
+
+ indent_down();
+ out << indent() << "}" << endl << endl;
+ }
+
+ // 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) {
+ out <<
+ indent() <<
+ indent() << "__isset." << (*m_iter)->get_name() << " = true;" << endl;
+ }
+ out <<
+ indent()<< "}" << endl;
+ }
+ out << endl;
+}
/**
* Writes the fingerprint of a struct to either the header or implementation.
*
// TODO(dreiss): Why is this stuff not in generate_function_helpers?
ts->set_name(tservice->get_name() + "_" + (*f_iter)->get_name() + "_args");
- generate_struct_definition(f_header_, ts, false);
+ generate_struct_declaration(f_header_, 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_definition(f_header_, ts, false, true, false, true);
+ generate_struct_declaration(f_header_, ts, false, true, false, true);
generate_struct_writer(out, ts, true);
ts->set_name(name_orig);
result.append(*f_iter);
}
- generate_struct_definition(f_header_, &result, false);
+ generate_struct_declaration(f_header_, &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_definition(f_header_, &result, false, true, true, gen_cob_style_);
+ generate_struct_declaration(f_header_, &result, false, true, true, gen_cob_style_);
generate_struct_reader(out, &result, true);
if (gen_cob_style_) {
generate_struct_writer(out, &result, true);
string name = prefix + tfield->get_name() + suffix;
if (type->is_struct() || type->is_xception()) {
- generate_deserialize_struct(out, (t_struct*)type, name);
+ 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()) {
*/
void t_cpp_generator::generate_deserialize_struct(ofstream& out,
t_struct* tstruct,
- string prefix) {
- (void) tstruct;
- indent(out) <<
- "xfer += " << prefix << ".read(iprot);" << endl;
+ string prefix,
+ bool pointer) {
+ if (pointer) {
+ indent(out) << "if (!" << prefix << ") { " << endl;
+ indent(out) << " " << prefix << " = new " << type_name(tstruct) << ";" << endl;
+ indent(out) << "}" << endl;
+ indent(out) <<
+ "xfer += " << prefix << "->read(iprot);" << endl;
+ indent(out) << "bool wasSet = false;" << endl;
+ const vector<t_field*>& members = tstruct->get_members();
+ vector<t_field*>::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 << " = NULL; }" << endl;
+ } else {
+ indent(out) <<
+ "xfer += " << prefix << ".read(iprot);" << endl;
+ }
}
void t_cpp_generator::generate_deserialize_container(ofstream& out,
if (type->is_struct() || type->is_xception()) {
generate_serialize_struct(out,
(t_struct*)type,
- name);
+ name,
+ is_reference(tfield));
} else if (type->is_container()) {
generate_serialize_container(out, type, name);
} else if (type->is_base_type() || type->is_enum()) {
*/
void t_cpp_generator::generate_serialize_struct(ofstream& out,
t_struct* tstruct,
- string prefix) {
- (void) tstruct;
- indent(out) <<
- "xfer += " << prefix << ".write(oprot);" << endl;
+ 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(ofstream& out,
// Generate structs, exceptions, and unions in declared order
vector<t_struct*> objects = program_->get_objects();
+
vector<t_struct*>::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);
}
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);
}
// Scope accessor
- t_scope* scope() {
+ t_scope* scope() const {
return scope_;
}
return program_;
}
+ const t_program* get_program() const {
+ return program_;
+ }
+
t_type* get_true_type();
// Return a string that uniquely identifies this type
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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 <cstdio>
+
+#include "t_typedef.h"
+#include "t_program.h"
+
+t_type* t_typedef::get_type() const {
+ if (type_ == NULL) {
+ t_type* type = get_program()->scope()->get_type(symbolic_);
+ if (type == NULL) {
+ printf("Type \"%s\" not defined\n", symbolic_.c_str());
+ exit(1);
+ }
+ return type;
+ }
+ return type_;
+}
*/
class t_typedef : public t_type {
public:
- t_typedef(t_program* program, t_type* type, std::string symbolic) :
+ t_typedef(t_program* program, t_type* type, const std::string& symbolic) :
t_type(program, symbolic),
type_(type),
- symbolic_(symbolic) {}
+ symbolic_(symbolic),
+ seen_(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) :
+ t_type(program, symbolic),
+ type_(NULL),
+ symbolic_(symbolic),
+ seen_(false) {}
~t_typedef() {}
- t_type* get_type() const {
- return type_;
- }
+ t_type* get_type() const;
const std::string& get_symbolic() const {
return symbolic_;
}
virtual std::string get_fingerprint_material() const {
- return type_->get_fingerprint_material();
+ if (!seen_) {
+ seen_ = true;
+ std::string ret = get_type()->get_fingerprint_material();
+ seen_ = false;
+ return ret;
+ }
+ return "";
}
virtual void generate_fingerprint() {
t_type::generate_fingerprint();
- if (!type_->has_fingerprint()) {
- type_->generate_fingerprint();
+ if (!get_type()->has_fingerprint()) {
+ get_type()->generate_fingerprint();
}
}
private:
t_type* type_;
std::string symbolic_;
+ mutable bool seen_;
};
#endif
// Lookup the identifier in the current scope
$$ = g_scope->get_type($1);
if ($$ == NULL) {
- yyerror("Type \"%s\" has not been defined.", $1);
- exit(1);
+ /*
+ * 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);
}
}
}
gen-cpp/ThriftTest_types.cpp \
gen-cpp/DebugProtoTest_types.h \
gen-cpp/OptionalRequiredTest_types.h \
+ gen-cpp/Recursive_types.cpp \
+ gen-cpp/Recursive_types.h \
gen-cpp/ThriftTest_types.h \
ThriftTest_extras.cpp \
DebugProtoTest_extras.cpp
DebugProtoTest \
JSONProtoTest \
OptionalRequiredTest \
+ RecursiveTest \
SpecializationTest \
AllProtocolsTest \
TransportTest \
OptionalRequiredTest_LDADD = libtestgencpp.la
+#
+# OptionalRequiredTest
+#
+RecursiveTest_SOURCES = \
+ RecursiveTest.cpp
+
+RecursiveTest_LDADD = libtestgencpp.la
+
#
# SpecializationTest
#
gen-cpp/OptionalRequiredTest_types.cpp gen-cpp/OptionalRequiredTest_types.h: $(top_srcdir)/test/OptionalRequiredTest.thrift
$(THRIFT) --gen cpp:dense $<
+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:dense $<
--- /dev/null
+#! /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
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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 <thrift/transport/TBufferTransports.h>
+#include <thrift/protocol/TBinaryProtocol.h>
+
+using apache::thrift::transport::TMemoryBuffer;
+using apache::thrift::protocol::TBinaryProtocol;
+ using boost::shared_ptr;
+
+int main() {
+ shared_ptr<TMemoryBuffer> buf(new TMemoryBuffer());
+ shared_ptr<TBinaryProtocol> prot(new TBinaryProtocol(buf));
+
+ RecTree tree;
+ RecTree child;
+ tree.children.push_back(child);
+
+ tree.write(prot.get());
+
+ RecTree result;
+ result.read(prot.get());
+ assert(tree == result);
+
+ RecList l;
+ RecList* l2(new RecList);
+ l.nextitem = l2;
+
+ l.write(prot.get());
+
+ RecList resultlist;
+ resultlist.read(prot.get());
+ assert(resultlist.nextitem != NULL);
+ assert(resultlist.nextitem->nextitem == NULL);
+
+ CoRec c;
+ CoRec2* r(new CoRec2);
+ c.other = r;
+
+ c.write(prot.get());
+
+ c.read(prot.get());
+ assert(c.other != NULL);
+ assert(c.other->other.other == NULL);
+
+}
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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<RecTree> children
+ 2: i16 item
+}
+
+struct RecList {
+ 1: RecList nextitem (cpp.ref = "true")
+ 3: i16 item
+}
+
+struct CoRec {
+ 1: CoRec2 other (cpp.ref = "true")
+}
+
+struct CoRec2 {
+ 1: CoRec other
+}
+
+struct VectorTest {
+ 1: list<RecList> lister;
+}
+
+service TestService
+{
+ RecTree echoTree(1:RecTree tree)
+ RecList echoList(1:RecList lst)
+ CoRec echoCoRec(1:CoRec item)
+}