Initial struct marshalling.
[polintos/scott/priv.git] / idlcomp / languages / c++ / marshall.cc
index 46621fed92db8b5e371042d83961a3cdb43f5821..8ab02e0bbc786189a1483316571ba0db55496dbb 100644 (file)
@@ -1,6 +1,6 @@
 // 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
@@ -31,60 +31,150 @@ void CPPFile::output_ifaceinfo(Interface *iface)
             << 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";
        }
 }
 
@@ -95,17 +185,34 @@ void CPPFile::output_marshall(Interface *sym, Datum *d)
 
 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)
@@ -114,30 +221,39 @@ 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;
        }