Virtual structs are prefaced with a header, which consists of
the following, in order:
-1. 128-bit GUID of the most derived vstruct type
-2. 160-bit SHA-1 of the vstruct type info
-3. 32-bit objlist-offset of an introspection object
-4. 32-bit length of vstruct, including header, and all referenced
+1. 32-bit length of vstruct, including header, and all referenced
data chunks, which must be contiguously appended to the vstruct body
-5. 32-bit reserved field
+2. 32-bit offset of start of actual struct
+3. 128-bit GUID of the most derived vstruct type
+5. 32-bit objlist-offset of the vstruct's object handles, the first
+of which is introspection object
+6. 32-bit length of vstruct objlist in handles
+7. 32-bit offset of an area within the vstruct where the objlist can
+be copied.
+8. 32-bit reserved field
The requirement for all referenced data chunks to be contiguous with
the vstruct means that scatter-gather and zero-copy cannot be done;
process that does know the derived type). For this reason, vstructs
should generally not be used to pass large chunks of data.
-The introspection object reference may be NULL; in this case, the
-SHA-1 field is ignored.
+Likewise, object handles must be preserved even if they are only
+referenced in an unknown-type portion of the vstruct. To facilitate
+this, all handles referenced from the vstruct must be contiguous in
+the objlist (even if this means duplications), and there must be an
+area in the vstruct blob where unmarshalling code can copy the
+translated objlist.
+
+The introspection object reference at the beginning of the vstruct
+objlist may be NULL.
Op1: Get Interface List
-----------------------
// idlcomp/languages/c++/main.cc -- C++ IDL binding
//
+// A lot of the complexity in here would just go away if C++ could handle
+// out-of-order declarations.
+//
// This software is copyright (c) 2006 Scott Wood <scott@buserror.net>.
//
// This software is provided 'as-is', without any express or implied warranty.
cpp_output_name(file, t);
- if (array)
+ if (array) {
+ Struct *str = dynamic_cast<Struct *>(t);
+ if (str)
+ file << " *";
+
file << ", ::System::RunTime::ORBMM>";
+ }
file << ' ';
}
!d->def.flags.field.Immutable);
Struct *dtype = dynamic_cast<Struct *>(*d->type);
- if (dtype && !dtype->is_inline())
+ if (dtype && !dtype->is_inline() && !d->is_array())
file << '*';
} else {
cpp_output_type(file, d->def.basictype,
{
switch (pass) {
case trav_nsdecl:
+ // If indent level is not zero, this is a nested struct or interface.
+ if (indent.indent_level == 0)
+ output_pass(sym, trav_forward);
+
if (sym->is_virtual()) {
output_nsdecl_begin(sym);
output_nsdecl_children(sym);
output_struct_ctor(sym, true);
}
- output_marshall_pass(sym, trav_full);
-
upscope();
file << indent << "};\n";
-
+
ns_out(sym);
+
+ all_ns_in(sym, true, "MARSHALL_");
+ output_marshall_pass(sym, trav_full);
+ all_ns_out(sym, true);
output_aliases_and_types(sym);
}
}
-
void CPPFile::output(Enum *sym, int pass, void *arg2)
{
switch (pass) {
// C++ Marshalling
//
-// This software is copyright (c) 2007 Scott Wood <scott@buserror.net>.
+// This software is copyright (c) 2008 Scott Wood <scott@buserror.net>.
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors or contributors be held liable for any damages
<< indent << "};\n";
}
-void CPPFile::output_marshall(CompiledBasicType &cbt, Datum *d)
-{
- printf("marshall cbt\n");
-}
-
void CPPFile::align_type(Symbol *sym)
{
- file << indent << "_ctx.buf.align_to(__alignof__(";
+ file << '\n'
+ << indent << "ctx.buf.align_to(__alignof__(";
cpp_output_name(file, sym);
file << "));\n";
}
-void CPPFile::grow_buf(Symbol *sym)
+void CPPFile::grow_buf()
+{
+ file << indent << "ptr = ctx.buf.grow_by(len);\n";
+}
+
+void CPPFile::marshall_members(Struct *sym)
+{
+ for (Struct::entries_iterator i = sym->entries_begin();
+ i != sym->entries_end(); ++i)
+ {
+ Datum *member = *i;
+
+ if (member->type)
+ member->type->output_lang(this, trav_marshall, member);
+ else
+ output_marshall(member->def.basictype, member);
+ }
+}
+
+void CPPFile::output_marshall_array(Datum *d)
+{
+ file << '\n'
+ << indent << "ctx.buf.align_to(__alignof__(*data->" << **d->name << ".ptr));\n"
+ << indent << "len = data->" << **d->name
+ << ".count * sizeof(*data->" << **d->name << ".ptr);\n";
+
+ grow_buf();
+
+ file << indent << "memcpy(ptr, data->" << **d->name << ".ptr, len);\n";
+}
+
+void CPPFile::output_marshall_method(Struct *sym)
{
- file << indent << "_ptr = _ctx.buf.grow_by(sizeof(";
+ file << indent << "__attribute__((weak)) __attribute__((unused))\n"
+ << indent << "void *_marshall(::System::RunTime::MarshCtx &ctx, ";
cpp_output_name(file, sym);
- file << "));\n";
+ file << " *data, ";
+ cpp_output_name(file, sym);
+ file << " **link)\n"
+ << indent << "{\n";
+
+ indent.indent_level++;
+
+ file << indent;
+ cpp_output_name(file, sym);
+ file << " *sptr;\n"
+ << indent << "void *ptr;\n"
+ << indent << "size_t len;\n"
+ << indent << "__attribute__((unused)) size_t i = 0;\n";
+
+ align_type(sym);
+ file << indent << "*link = (";
+ cpp_output_name(file, sym);
+ file << " *)ctx.buf.count;\n";
+ file << indent << "len = sizeof(*data);\n";
+ grow_buf();
+
+ file << indent << "memcpy(ptr, data, len);\n"
+ << indent << "sptr = (";
+ cpp_output_name(file, sym);
+ file << " *)ptr;\n";
+
+ marshall_members(sym);
+ indent.indent_level--;
+
+ file << indent << "\treturn 0;\n"
+ << indent << "}\n\n";
}
-void CPPFile::output_marshall(Struct *sym, Datum *d)
+void CPPFile::output_marshall_inline_method(Struct *sym)
{
- bool is_inline = !d || d->is_inline();
+ file << indent << "__attribute__((weak)) __attribute__((unused))\n"
+ << indent << "void *_marshall_inline(::System::RunTime::MarshCtx &ctx, ";
+ cpp_output_name(file, sym);
+ file << " *data, ";
+ cpp_output_name(file, sym);
+ file << " *sptr)\n"
+ << indent << "{\n";
- if (d && !d->is_inline()) {
- extra_newline();
- file << indent << "if (" << **d->name << ")\n"
- << indent << '\t' << **d->name << "->_marshall(_ctx);\n";
+ indent.indent_level++;
- return;
- }
+ file << indent << "__attribute__((unused)) void *ptr;\n"
+ << indent << "__attribute__((unused)) size_t len;\n"
+ << indent << "__attribute__((unused)) size_t i = 0;\n";
- if (!d) {
- extra_newline();
- align_type(sym);
- grow_buf(sym);
+ marshall_members(sym);
+ indent.indent_level--;
+
+ file << indent << "\treturn 0;\n"
+ << indent << "}\n";
+}
+
+void CPPFile::output_marshall(Struct *sym, Datum *d)
+{
+ bool array = d->is_array(), inl = d->is_inline();
+ const char *index = "";
+
+ file << '\n';
+
+ if (array) {
+ file << indent << "for (size_t i = 0; i < ";
- file << indent << "memcpy(_ptr, this, sizeof(*this));\n";
+ if (inl)
+ file << d->array->cons[0].con.ucon;
+ else
+ file << "data->" << **d->name << ".count";
+
+ file << "; i++) {\n";
+
+ indent.indent_level++;
+ index = "[i]";
}
- if (sym->is_plain_data()) {
- printf("plain data\n");
- return;
+ if (!inl) {
+ file << indent << "if (data->" << **d->name << index << ")\n";
+ indent.indent_level++;
}
- for (Struct::entries_iterator i = sym->entries_begin();
- i != sym->entries_end(); ++i)
- {
- extra_newline();
- Datum *d = *i;
-
- if (d->type)
- d->type->output_lang(this, trav_marshall, d);
- else
- output_marshall(d->def.basictype, d);
+ file << indent;
+ cpp_output_name(file, sym);
+ file << "_ns::_marshall";
+
+ if (inl)
+ file << "_inline(ctx, &";
+ else
+ file << "(ctx, ";
+
+ file << "data->" << **d->name << index
+ << ", &sptr->" << **d->name << index << ");\n";
+
+ if (!inl)
+ indent.indent_level--;
+
+ if (array) {
+ indent.indent_level--;
+ file << indent << "}\n";
}
}
void CPPFile::output_marshall(Enum *sym, Datum *d)
{
- printf("marshall enum\n");
+ if (!d->is_array() || d->is_inline())
+ return;
+
+ output_marshall_array(d);
}
void CPPFile::output_marshall(BitField *sym, Datum *d)
{
- printf("marshall bitfield\n");
+ if (!d->is_array() || d->is_inline())
+ return;
+
+ output_marshall_array(d);
}
void CPPFile::output_marshall(BasicType *sym, Datum *d)
{
- printf("marshall basictype\n");
+ if (!d->is_array() || d->is_inline())
+ return;
+
+ output_marshall_array(d);
+}
+
+void CPPFile::output_marshall(CompiledBasicType &cbt, Datum *d)
+{
+ if (!d->is_array() || d->is_inline())
+ return;
+
+ output_marshall_array(d);
}
void CPPFile::output_marshall_pass(Struct *sym, int pass)
case trav_nsdecl:
extra_newline();
- file << indent << "int _marshall(::System::RunTime::MarshCtx &_ctx);\n";
- file << indent << "void _unmarshall(::System::RunTime::MarshCtx &_ctx);\n";
- break;
-
- case trav_full:
- extra_newline();
+ file << indent << "void *_marshall(::System::RunTime::MarshCtx &ctx,\n"
+ << indent << " ";
+ cpp_output_name(file, sym);
+ file << " *data, ";
+ cpp_output_name(file, sym);
+ file << " **link);\n";
- file << indent << "int _marshall(::System::RunTime::MarshCtx &_ctx)\n"
- << indent << "{\n"
- << indent << "\tvoid *_ptr;\n";
+ file << indent << "void *_marshall_inline(::System::RunTime::MarshCtx &ctx,\n"
+ << indent << " ";
+ cpp_output_name(file, sym);
+ file << " *data, ";
+ cpp_output_name(file, sym);
+ file << " *sptr);\n";
- indent.indent_level++;
- output_marshall(sym, NULL);
- indent.indent_level--;
+ file << indent << "void _unmarshall(::System::RunTime::MarshCtx &ctx,\n"
+ << indent << " ";
+ cpp_output_name(file, sym);
+ file << " *data);\n";
+ break;
- file << indent << "\treturn 0;\n"
- << indent << "}\n\n";
+ case trav_full:
+ output_marshall_method(sym);
+ output_marshall_inline_method(sym);
- file << indent << "void _unmarshall(::System::RunTime::Array<uint8_t, ::System::RunTime::ORBMM> buf,\n"
+#if 0
+ file << indent << "__attribute__((weak)) __attribute__((unused))\n"
+ << indent << "void _unmarshall(::System::RunTime::Array<uint8_t, ::System::RunTime::ORBMM> buf,\n"
<< indent << " ::System::RunTime::Array< ::System::_i_Object *, ::System::RunTime::ORBMM> objlist,\n"
<< indent << " ::System::RunTime::ParamInfoBlock::Segment *segs,\n"
<< indent << " int nsegs)\n"
<< indent << "{\n"
<< indent << "}\n";
+#endif
break;
}