1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4
5 #include "Gen.h"
6 #include <Slice/Util.h>
7 #include <Slice/CPlusPlusUtil.h>
8 #include <IceUtil/Functional.h>
9 #include <IceUtil/Iterator.h>
10 #include <IceUtil/StringUtil.h>
11 #include <Slice/Checksum.h>
12 #include <Slice/FileTracker.h>
13 #include <IceUtil/FileUtil.h>
14
15 #include <limits>
16 #include <string.h>
17
18 using namespace std;
19 using namespace Slice;
20 using namespace IceUtil;
21 using namespace IceUtilInternal;
22
23 namespace
24 {
25
26 bool
isConstexprType(const TypePtr & type)27 isConstexprType(const TypePtr& type)
28 {
29 BuiltinPtr bp = BuiltinPtr::dynamicCast(type);
30 if(bp)
31 {
32 switch(bp->kind())
33 {
34 case Builtin::KindByte:
35 case Builtin::KindBool:
36 case Builtin::KindShort:
37 case Builtin::KindInt:
38 case Builtin::KindLong:
39 case Builtin::KindFloat:
40 case Builtin::KindDouble:
41 case Builtin::KindValue:
42 case Builtin::KindObject:
43 case Builtin::KindObjectProxy:
44 {
45 return true;
46 }
47 default:
48 {
49 return false;
50 }
51 }
52 }
53 else if(EnumPtr::dynamicCast(type) || ProxyPtr::dynamicCast(type) || ClassDeclPtr::dynamicCast(type))
54 {
55 return true;
56 }
57 else
58 {
59 StructPtr s = StructPtr::dynamicCast(type);
60 if(s)
61 {
62 DataMemberList members = s->dataMembers();
63 for(DataMemberList::const_iterator i = members.begin(); i != members.end(); ++i)
64 {
65 if(!isConstexprType((*i)->type()))
66 {
67 return false;
68 }
69 }
70 return true;
71 }
72 return false;
73 }
74 }
75
76 string
getDeprecateSymbol(const ContainedPtr & p1,const ContainedPtr & p2)77 getDeprecateSymbol(const ContainedPtr& p1, const ContainedPtr& p2)
78 {
79 string deprecateMetadata, deprecateSymbol;
80 if(p1->findMetaData("deprecate", deprecateMetadata) ||
81 (p2 != 0 && p2->findMetaData("deprecate", deprecateMetadata)))
82 {
83 string msg = "is deprecated";
84 if(deprecateMetadata.find("deprecate:") == 0 && deprecateMetadata.size() > 10)
85 {
86 msg = deprecateMetadata.substr(10);
87 }
88 deprecateSymbol = "ICE_DEPRECATED_API(\"" + msg + "\") ";
89 }
90 return deprecateSymbol;
91 }
92
93 void
writeConstantValue(IceUtilInternal::Output & out,const TypePtr & type,const SyntaxTreeBasePtr & valueType,const string & value,int typeContext,const StringList & metaData,const string & scope)94 writeConstantValue(IceUtilInternal::Output& out, const TypePtr& type, const SyntaxTreeBasePtr& valueType,
95 const string& value, int typeContext, const StringList& metaData, const string& scope)
96 {
97 ConstPtr constant = ConstPtr::dynamicCast(valueType);
98 if(constant)
99 {
100 out << getUnqualified(fixKwd(constant->scoped()), scope);
101 }
102 else
103 {
104 bool cpp11 = (typeContext & TypeContextCpp11) == TypeContextCpp11;
105 BuiltinPtr bp = BuiltinPtr::dynamicCast(type);
106 if(bp && bp->kind() == Builtin::KindString)
107 {
108 bool wide = (typeContext & TypeContextUseWstring) || findMetaData(metaData) == "wstring";
109 if(wide || cpp11)
110 {
111 out << (wide ? "L\"" : "u8\"");
112 out << toStringLiteral(value, "\a\b\f\n\r\t\v", "?", UCN, cpp11 ? 0 : 0x9F + 1);
113 out << "\"";
114 }
115 else // C++98 narrow strings
116 {
117 out << "\"" << toStringLiteral(value, "\a\b\f\n\r\t\v", "?", Octal, 0) << "\"";
118 }
119 }
120 else if(bp && bp->kind() == Builtin::KindLong)
121 {
122 if(cpp11)
123 {
124 out << value << "LL";
125 }
126 else
127 {
128 out << "ICE_INT64(" << value << ")";
129 }
130 }
131 else if(bp && bp->kind() == Builtin::KindFloat)
132 {
133 out << value;
134 if(value.find(".") == string::npos)
135 {
136 out << ".0";
137 }
138 out << "F";
139 }
140 else
141 {
142 EnumPtr ep = EnumPtr::dynamicCast(type);
143 if(ep && valueType)
144 {
145 EnumeratorPtr enumerator = EnumeratorPtr::dynamicCast(valueType);
146 assert(enumerator);
147
148 bool unscoped = (cpp11 && findMetaData(ep->getMetaData(), TypeContextCpp11) == "%unscoped") ||
149 (!cpp11 && findMetaData(ep->getMetaData()) != "%scoped");
150
151 if(unscoped)
152 {
153 out << getUnqualified(fixKwd(ep->scope() + enumerator->name()), scope);
154 }
155 else
156 {
157 if(cpp11)
158 {
159 out << getUnqualified(fixKwd(enumerator->scoped()), scope);
160 }
161 else
162 {
163 out << getUnqualified(fixKwd(ep->scope() + ep->name() + enumerator->name()), scope);
164 }
165 }
166 }
167 else if(!ep)
168 {
169 out << value;
170 }
171 }
172 }
173 }
174
175 string
toDllClassExport(const string & dllExport)176 toDllClassExport(const string& dllExport)
177 {
178 if(!dllExport.empty())
179 {
180 return "ICE_CLASS(" + dllExport.substr(0, dllExport.size() - 1) + ") ";
181 }
182 else
183 {
184 return "";
185 }
186 }
187
188 string
toDllMemberExport(const string & dllExport)189 toDllMemberExport(const string& dllExport)
190 {
191 if(!dllExport.empty())
192 {
193 return "ICE_MEMBER(" + dllExport.substr(0, dllExport.size() - 1) + ") ";
194 }
195 else
196 {
197 return "";
198 }
199 }
200
201 void
writeDataMemberInitializers(IceUtilInternal::Output & C,const DataMemberList & members,int typeContext)202 writeDataMemberInitializers(IceUtilInternal::Output& C, const DataMemberList& members, int typeContext)
203 {
204 bool first = true;
205 for(DataMemberList::const_iterator p = members.begin(); p != members.end(); ++p)
206 {
207 ContainedPtr contained = ContainedPtr::dynamicCast((*p)->container());
208 string scope = contained->scope();
209 if((*p)->defaultValueType())
210 {
211 string memberName = fixKwd((*p)->name());
212
213 if(first)
214 {
215 first = false;
216 }
217 else
218 {
219 C << ',';
220 }
221 C << nl << memberName << '(';
222 writeConstantValue(C, (*p)->type(), (*p)->defaultValueType(), (*p)->defaultValue(), typeContext,
223 (*p)->getMetaData(), scope);
224 C << ')';
225 }
226 }
227 }
228
229 void
writeInParamsLambda(IceUtilInternal::Output & C,const OperationPtr & p,const ParamDeclList & inParams,const string & scope)230 writeInParamsLambda(IceUtilInternal::Output& C, const OperationPtr& p, const ParamDeclList& inParams,
231 const string& scope)
232 {
233 if(inParams.empty())
234 {
235 C << "nullptr";
236 }
237 else
238 {
239 C << "[&](" << getUnqualified("::Ice::OutputStream*", scope) << " ostr)";
240 C << sb;
241 writeMarshalCode(C, inParams, 0, true, TypeContextInParam | TypeContextCpp11);
242 if(p->sendsClasses(false))
243 {
244 C << nl << "ostr->writePendingValues();";
245 }
246 C << eb;
247 }
248 }
249
250 void
throwUserExceptionLambda(IceUtilInternal::Output & C,ExceptionList throws,const string & scope)251 throwUserExceptionLambda(IceUtilInternal::Output& C, ExceptionList throws, const string& scope)
252 {
253 if(throws.empty())
254 {
255 C << "nullptr";
256 }
257 else
258 {
259 throws.sort();
260 throws.unique();
261
262 //
263 // Arrange exceptions into most-derived to least-derived order. If we don't
264 // do this, a base exception handler can appear before a derived exception
265 // handler, causing compiler warnings and resulting in the base exception
266 // being marshaled instead of the derived exception.
267 //
268 throws.sort(Slice::DerivedToBaseCompare());
269
270 C << "[](const " << getUnqualified("::Ice::UserException&", scope) << " ex)";
271 C << sb;
272 C << nl << "try";
273 C << sb;
274 C << nl << "ex.ice_throw();";
275 C << eb;
276 //
277 // Generate a catch block for each legal user exception.
278 //
279 for(ExceptionList::const_iterator i = throws.begin(); i != throws.end(); ++i)
280 {
281 string scoped = (*i)->scoped();
282 C << nl << "catch(const " << getUnqualified(fixKwd((*i)->scoped()), scope) << "&)";
283 C << sb;
284 C << nl << "throw;";
285 C << eb;
286 }
287 C << nl << "catch(const " << getUnqualified("::Ice::UserException&", scope) << ")";
288 C << sb;
289 C << eb;
290 C << eb;
291 }
292 }
293
294 string
resultStructName(const string & name,const string & scope="",bool marshaledResult=false)295 resultStructName(const string& name, const string& scope = "", bool marshaledResult = false)
296 {
297 assert(!name.empty());
298 string stName = IceUtilInternal::toUpper(name.substr(0, 1)) + name.substr(1);
299 stName += marshaledResult ? "MarshaledResult" : "Result";
300 if(!scope.empty())
301 {
302 stName = scope + "::" + stName;
303 }
304 return stName;
305 }
306
307 string
condMove(bool moveIt,const string & str)308 condMove(bool moveIt, const string& str)
309 {
310 return moveIt ? string("::std::move(") + str + ")" : str;
311 }
312
313 string
escapeParam(const ParamDeclList & params,const string & name)314 escapeParam(const ParamDeclList& params, const string& name)
315 {
316 string r = name;
317 for(ParamDeclList::const_iterator p = params.begin(); p != params.end(); ++p)
318 {
319 if(fixKwd((*p)->name()) == name)
320 {
321 r = name + "_";
322 break;
323 }
324 }
325 return r;
326 }
327
328 void
writeDocLines(Output & out,const StringList & lines,bool commentFirst,const string & space=" ")329 writeDocLines(Output& out, const StringList& lines, bool commentFirst, const string& space = " ")
330 {
331 StringList l = lines;
332 if(!commentFirst)
333 {
334 out << l.front();
335 l.pop_front();
336 }
337 for(StringList::const_iterator i = l.begin(); i != l.end(); ++i)
338 {
339 out << nl << " *";
340 if(!i->empty())
341 {
342 out << space << *i;
343 }
344 }
345 }
346
347 void
writeSeeAlso(Output & out,const StringList & lines,const string & space=" ")348 writeSeeAlso(Output& out, const StringList& lines, const string& space = " ")
349 {
350 for(StringList::const_iterator i = lines.begin(); i != lines.end(); ++i)
351 {
352 out << nl << " *";
353 if(!i->empty())
354 {
355 out << space << "@see " << *i;
356 }
357 }
358 }
359
360 string
getDocSentence(const StringList & lines)361 getDocSentence(const StringList& lines)
362 {
363 //
364 // Extract the first sentence.
365 //
366 ostringstream ostr;
367 for(StringList::const_iterator i = lines.begin(); i != lines.end(); ++i)
368 {
369 const string ws = " \t";
370
371 if(i->empty())
372 {
373 break;
374 }
375 if(i != lines.begin() && i->find_first_not_of(ws) == 0)
376 {
377 ostr << " ";
378 }
379 string::size_type pos = i->find('.');
380 if(pos == string::npos)
381 {
382 ostr << *i;
383 }
384 else if(pos == i->size() - 1)
385 {
386 ostr << *i;
387 break;
388 }
389 else
390 {
391 //
392 // Assume a period followed by whitespace indicates the end of the sentence.
393 //
394 while(pos != string::npos)
395 {
396 if(ws.find((*i)[pos + 1]) != string::npos)
397 {
398 break;
399 }
400 pos = i->find('.', pos + 1);
401 }
402 if(pos != string::npos)
403 {
404 ostr << i->substr(0, pos + 1);
405 break;
406 }
407 else
408 {
409 ostr << *i;
410 }
411 }
412 }
413
414 return ostr.str();
415 }
416
417 void
writeDocSummary(Output & out,const ContainedPtr & p)418 writeDocSummary(Output& out, const ContainedPtr& p)
419 {
420 if(p->comment().empty())
421 {
422 return;
423 }
424
425 CommentPtr doc = p->parseComment(false);
426
427 out << nl << "/**";
428
429 if(!doc->overview().empty())
430 {
431 writeDocLines(out, doc->overview(), true);
432 }
433
434 if(!doc->misc().empty())
435 {
436 writeDocLines(out, doc->misc(), true);
437 }
438
439 if(!doc->seeAlso().empty())
440 {
441 writeSeeAlso(out, doc->seeAlso());
442 }
443
444 if(!doc->deprecated().empty())
445 {
446 out << nl << " *";
447 out << nl << " * @deprecated ";
448 writeDocLines(out, doc->deprecated(), false);
449 }
450 else if(doc->isDeprecated())
451 {
452 out << nl << " *";
453 out << nl << " * @deprecated";
454 }
455
456 switch(p->containedType())
457 {
458 case Contained::ContainedTypeClass:
459 case Contained::ContainedTypeStruct:
460 case Contained::ContainedTypeException:
461 {
462 UnitPtr unt = p->container()->unit();
463 string file = p->file();
464 assert(!file.empty());
465 static const string prefix = "cpp:doxygen:include:";
466 DefinitionContextPtr dc = unt->findDefinitionContext(file);
467 assert(dc);
468 string q = dc->findMetaData(prefix);
469 if(!q.empty())
470 {
471 out << nl << " * \\headerfile " << q.substr(prefix.size());
472 }
473 break;
474 }
475 default:
476 break;
477 }
478
479 out << nl << " */";
480 }
481
482 enum OpDocParamType { OpDocInParams, OpDocOutParams, OpDocAllParams };
483
484 void
writeOpDocParams(Output & out,const OperationPtr & op,const CommentPtr & doc,OpDocParamType type,const StringList & preParams=StringList (),const StringList & postParams=StringList ())485 writeOpDocParams(Output& out, const OperationPtr& op, const CommentPtr& doc, OpDocParamType type,
486 const StringList& preParams = StringList(), const StringList& postParams = StringList())
487 {
488 ParamDeclList params;
489 switch(type)
490 {
491 case OpDocInParams:
492 params = op->inParameters();
493 break;
494 case OpDocOutParams:
495 params = op->outParameters();
496 break;
497 case OpDocAllParams:
498 params = op->parameters();
499 break;
500 }
501
502 if(!preParams.empty())
503 {
504 writeDocLines(out, preParams, true);
505 }
506
507 map<string, StringList> paramDoc = doc->parameters();
508 for(ParamDeclList::iterator p = params.begin(); p != params.end(); ++p)
509 {
510 map<string, StringList>::iterator q = paramDoc.find((*p)->name());
511 if(q != paramDoc.end())
512 {
513 out << nl << " * @param " << fixKwd(q->first) << " ";
514 writeDocLines(out, q->second, false);
515 }
516 }
517
518 if(!postParams.empty())
519 {
520 writeDocLines(out, postParams, true);
521 }
522 }
523
524 void
writeOpDocExceptions(Output & out,const OperationPtr & op,const CommentPtr & doc)525 writeOpDocExceptions(Output& out, const OperationPtr& op, const CommentPtr& doc)
526 {
527 map<string, StringList> exDoc = doc->exceptions();
528 for(map<string, StringList>::iterator p = exDoc.begin(); p != exDoc.end(); ++p)
529 {
530 //
531 // Try to locate the exception's definition using the name given in the comment.
532 //
533 string name = p->first;
534 ExceptionPtr ex = op->container()->lookupException(name, false);
535 if(ex)
536 {
537 name = ex->scoped().substr(2);
538 }
539 out << nl << " * @throws " << name << " ";
540 writeDocLines(out, p->second, false);
541 }
542 }
543
544 void
writeOpDocSummary(Output & out,const OperationPtr & op,const CommentPtr & doc,OpDocParamType type,bool showExceptions,const StringList & preParams=StringList (),const StringList & postParams=StringList (),const StringList & returns=StringList ())545 writeOpDocSummary(Output& out, const OperationPtr& op, const CommentPtr& doc, OpDocParamType type, bool showExceptions,
546 const StringList& preParams = StringList(), const StringList& postParams = StringList(),
547 const StringList& returns = StringList())
548 {
549 out << nl << "/**";
550
551 if(!doc->overview().empty())
552 {
553 writeDocLines(out, doc->overview(), true);
554 }
555
556 writeOpDocParams(out, op, doc, type, preParams, postParams);
557
558 if(!returns.empty())
559 {
560 out << nl << " * @return ";
561 writeDocLines(out, returns, false);
562 }
563
564 if(showExceptions)
565 {
566 writeOpDocExceptions(out, op, doc);
567 }
568
569 if(!doc->misc().empty())
570 {
571 writeDocLines(out, doc->misc(), true);
572 }
573
574 if(!doc->seeAlso().empty())
575 {
576 writeSeeAlso(out, doc->seeAlso());
577 }
578
579 if(!doc->deprecated().empty())
580 {
581 out << nl << " *";
582 out << nl << " * @deprecated ";
583 writeDocLines(out, doc->deprecated(), false);
584 }
585 else if(doc->isDeprecated())
586 {
587 out << nl << " *";
588 out << nl << " * @deprecated";
589 }
590
591 out << nl << " */";
592 }
593
594 void
emitOpNameResult(IceUtilInternal::Output & H,const OperationPtr & p,int useWstring)595 emitOpNameResult(IceUtilInternal::Output& H, const OperationPtr& p, int useWstring)
596 {
597 string name = p->name();
598
599 ContainerPtr container = p->container();
600 ClassDefPtr cl = ClassDefPtr::dynamicCast(container);
601 string clScope = fixKwd(cl->scope());
602
603 TypePtr ret = p->returnType();
604 string retS = returnTypeToString(ret, p->returnIsOptional(), clScope, p->getMetaData(),
605 useWstring | TypeContextCpp11);
606
607 ParamDeclList outParams = p->outParameters();
608
609 if((outParams.size() > 1) || (ret && outParams.size() > 0))
610 {
611 //
612 // Generate OpNameResult struct
613 //
614 string returnValueS = "returnValue";
615
616 for(ParamDeclList::iterator q = outParams.begin(); q != outParams.end(); ++q)
617 {
618 if((*q)->name() == "returnValue")
619 {
620 returnValueS = "_returnValue";
621 }
622 }
623
624 H << sp;
625 H << nl << "/**";
626 H << nl << " * Encapsulates the results of a call to " << fixKwd(name) << ".";
627 H << nl << " */";
628 H << nl << "struct " << resultStructName(name);
629 H << sb;
630 CommentPtr comment = p->parseComment(false);
631 map<string, StringList> paramComments;
632 if(comment)
633 {
634 paramComments = comment->parameters();
635 }
636 if(ret)
637 {
638 if(comment && !comment->returns().empty())
639 {
640 H << nl << "/** " << getDocSentence(comment->returns()) << " */";
641 }
642 H << nl << retS << " " << returnValueS << ";";
643 }
644 for(ParamDeclList::iterator q = outParams.begin(); q != outParams.end(); ++q)
645 {
646 string typeString = typeToString((*q)->type(), (*q)->optional(), clScope, (*q)->getMetaData(),
647 useWstring | TypeContextCpp11);
648
649 map<string, StringList>::iterator r = paramComments.find((*q)->name());
650 if(r != paramComments.end())
651 {
652 H << nl << "/** " << getDocSentence(r->second) << " */";
653 }
654 H << nl << typeString << " " << fixKwd((*q)->name()) << ";";
655 }
656 H << eb << ";";
657 }
658 }
659
660 }
661
Gen(const string & base,const string & headerExtension,const string & sourceExtension,const vector<string> & extraHeaders,const string & include,const vector<string> & includePaths,const string & dllExport,const string & dir,bool implCpp98,bool implCpp11,bool checksum,bool ice)662 Slice::Gen::Gen(const string& base, const string& headerExtension, const string& sourceExtension,
663 const vector<string>& extraHeaders, const string& include,
664 const vector<string>& includePaths, const string& dllExport, const string& dir,
665 bool implCpp98, bool implCpp11, bool checksum, bool ice) :
666 _base(base),
667 _headerExtension(headerExtension),
668 _implHeaderExtension(headerExtension),
669 _sourceExtension(sourceExtension),
670 _extraHeaders(extraHeaders),
671 _include(include),
672 _includePaths(includePaths),
673 _dllExport(dllExport),
674 _dir(dir),
675 _implCpp98(implCpp98),
676 _implCpp11(implCpp11),
677 _checksum(checksum),
678 _ice(ice)
679 {
680 for(vector<string>::iterator p = _includePaths.begin(); p != _includePaths.end(); ++p)
681 {
682 *p = fullPath(*p);
683 }
684
685 string::size_type pos = _base.find_last_of("/\\");
686 if(pos != string::npos)
687 {
688 _base.erase(0, pos + 1);
689 }
690 }
691
~Gen()692 Slice::Gen::~Gen()
693 {
694 H << "\n\n#include <IceUtil/PopDisableWarnings.h>";
695 H << "\n#endif\n";
696 C << '\n';
697
698 if(_implCpp98 || _implCpp11)
699 {
700 implH << "\n\n#endif\n";
701 implC << '\n';
702 }
703 }
704
705 void
generateChecksumMap(const UnitPtr & p)706 Slice::Gen::generateChecksumMap(const UnitPtr& p)
707 {
708 if(_checksum)
709 {
710 ChecksumMap map = createChecksums(p);
711 if(!map.empty())
712 {
713 C << sp << nl << "namespace";
714 C << nl << "{";
715 C << sp << nl << "const char* iceSliceChecksums[] =";
716 C << sb;
717 for(ChecksumMap::const_iterator q = map.begin(); q != map.end(); ++q)
718 {
719 C << nl << "\"" << q->first << "\", \"";
720 ostringstream str;
721 str.flags(ios_base::hex);
722 str.fill('0');
723 for(vector<unsigned char>::const_iterator r = q->second.begin(); r != q->second.end(); ++r)
724 {
725 str << static_cast<int>(*r);
726 }
727 C << str.str() << "\",";
728 }
729 C << nl << "0";
730 C << eb << ';';
731 C << nl << "const IceInternal::SliceChecksumInit iceSliceChecksumInit(iceSliceChecksums);";
732 C << sp << nl << "}";
733 }
734 }
735 }
736
737 void
generate(const UnitPtr & p)738 Slice::Gen::generate(const UnitPtr& p)
739 {
740 string file = p->topLevelFile();
741
742 //
743 // Give precedence to header-ext/source-ext global metadata.
744 //
745 string headerExtension = getHeaderExt(file, p);
746 if(!headerExtension.empty())
747 {
748 _headerExtension = headerExtension;
749 }
750
751 string sourceExtension = getSourceExt(file, p);
752 if(!sourceExtension.empty())
753 {
754 _sourceExtension = sourceExtension;
755 }
756
757 //
758 // Give precedence to --dll-export command-line option
759 //
760 if(_dllExport.empty())
761 {
762 DefinitionContextPtr dc = p->findDefinitionContext(file);
763 assert(dc);
764 static const string dllExportPrefix = "cpp:dll-export:";
765 string meta = dc->findMetaData(dllExportPrefix);
766 if(meta.size() > dllExportPrefix.size())
767 {
768 _dllExport = meta.substr(dllExportPrefix.size());
769 }
770 }
771
772 if(_implCpp98 || _implCpp11)
773 {
774 string fileImplH = _base + "I." + _implHeaderExtension;
775 string fileImplC = _base + "I." + _sourceExtension;
776 if(!_dir.empty())
777 {
778 fileImplH = _dir + '/' + fileImplH;
779 fileImplC = _dir + '/' + fileImplC;
780 }
781
782 IceUtilInternal::structstat st;
783 if(!IceUtilInternal::stat(fileImplH, &st))
784 {
785 ostringstream os;
786 os << fileImplH << "' already exists - will not overwrite";
787 throw FileException(__FILE__, __LINE__, os.str());
788 }
789 if(!IceUtilInternal::stat(fileImplC, &st))
790 {
791 ostringstream os;
792 os << fileImplC << "' already exists - will not overwrite";
793 throw FileException(__FILE__, __LINE__, os.str());
794 }
795
796 implH.open(fileImplH.c_str());
797 if(!implH)
798 {
799 ostringstream os;
800 os << "cannot open `" << fileImplH << "': " << IceUtilInternal::errorToString(errno);
801 throw FileException(__FILE__, __LINE__, os.str());
802 }
803 FileTracker::instance()->addFile(fileImplH);
804
805 implC.open(fileImplC.c_str());
806 if(!implC)
807 {
808 ostringstream os;
809 os << "cannot open `" << fileImplC << "': " << IceUtilInternal::errorToString(errno);
810 throw FileException(__FILE__, __LINE__, os.str());
811 }
812 FileTracker::instance()->addFile(fileImplC);
813
814 string s = _base + "I." + _implHeaderExtension;
815 if(_include.size())
816 {
817 s = _include + '/' + s;
818 }
819 transform(s.begin(), s.end(), s.begin(), ToIfdef());
820 implH << "#ifndef __" << s << "__";
821 implH << "\n#define __" << s << "__";
822 implH << '\n';
823 }
824
825 string fileH = _base + "." + _headerExtension;
826 string fileC = _base + "." + _sourceExtension;
827 if(!_dir.empty())
828 {
829 fileH = _dir + '/' + fileH;
830 fileC = _dir + '/' + fileC;
831 }
832
833 H.open(fileH.c_str());
834 if(!H)
835 {
836 ostringstream os;
837 os << "cannot open `" << fileH << "': " << IceUtilInternal::errorToString(errno);
838 throw FileException(__FILE__, __LINE__, os.str());
839 }
840 FileTracker::instance()->addFile(fileH);
841
842 C.open(fileC.c_str());
843 if(!C)
844 {
845 ostringstream os;
846 os << "cannot open `" << fileC << "': " << IceUtilInternal::errorToString(errno);
847 throw FileException(__FILE__, __LINE__, os.str());
848 }
849 FileTracker::instance()->addFile(fileC);
850
851 printHeader(H);
852 printGeneratedHeader(H, _base + ".ice");
853 printHeader(C);
854 printGeneratedHeader(C, _base + ".ice");
855
856 string s = _base + "." + _headerExtension;
857 if(_include.size())
858 {
859 s = _include + '/' + s;
860 }
861 transform(s.begin(), s.end(), s.begin(), ToIfdef());
862 H << "\n#ifndef __" << s << "__";
863 H << "\n#define __" << s << "__";
864 H << '\n';
865
866 validateMetaData(p);
867
868 writeExtraHeaders(C);
869
870 if(_dllExport.size())
871 {
872 C << "\n#ifndef " << _dllExport << "_EXPORTS";
873 C << "\n# define " << _dllExport << "_EXPORTS";
874 C << "\n#endif";
875 }
876
877 C << "\n#include <";
878 if(_include.size())
879 {
880 C << _include << '/';
881 }
882 C << _base << "." << _headerExtension << ">";
883 C << "\n#include <IceUtil/PushDisableWarnings.h>";
884
885 H << "\n#include <IceUtil/PushDisableWarnings.h>";
886 H << "\n#include <Ice/ProxyF.h>";
887 H << "\n#include <Ice/ObjectF.h>";
888 H << "\n#include <Ice/ValueF.h>";
889 H << "\n#include <Ice/Exception.h>";
890 H << "\n#include <Ice/LocalObject.h>";
891 H << "\n#include <Ice/StreamHelpers.h>";
892 H << "\n#include <Ice/Comparable.h>";
893
894 if(p->hasNonLocalClassDefs())
895 {
896 H << "\n#include <Ice/Proxy.h>";
897 H << "\n#include <Ice/Object.h>";
898 H << "\n#include <Ice/GCObject.h>";
899 H << "\n#include <Ice/Value.h>";
900 H << "\n#include <Ice/Incoming.h>";
901 if(p->hasContentsWithMetaData("amd"))
902 {
903 H << "\n#include <Ice/IncomingAsync.h>";
904 }
905 C << "\n#include <Ice/LocalException.h>";
906 C << "\n#include <Ice/ValueFactory.h>";
907 C << "\n#include <Ice/OutgoingAsync.h>";
908 }
909 else if(p->hasLocalClassDefsWithAsync())
910 {
911 H << "\n#include <Ice/OutgoingAsync.h>";
912 }
913 else if(p->hasNonLocalClassDecls())
914 {
915 H << "\n#include <Ice/Proxy.h>";
916 }
917
918 if(p->hasNonLocalClassDefs() || p->hasNonLocalExceptions())
919 {
920 H << "\n#include <Ice/FactoryTableInit.h>";
921 }
922
923 H << "\n#include <IceUtil/ScopedArray.h>";
924 H << "\n#include <Ice/Optional.h>";
925
926 if(p->hasExceptions())
927 {
928 H << "\n#include <Ice/ExceptionHelpers.h>";
929 }
930
931 if(p->usesNonLocals())
932 {
933 C << "\n#include <Ice/InputStream.h>";
934 C << "\n#include <Ice/OutputStream.h>";
935 }
936
937 if(p->hasNonLocalExceptions())
938 {
939 C << "\n#include <Ice/LocalException.h>";
940 }
941
942 if(p->hasContentsWithMetaData("preserve-slice"))
943 {
944 H << "\n#include <Ice/SlicedDataF.h>";
945 C << "\n#include <Ice/SlicedData.h>";
946 }
947
948 if(_checksum)
949 {
950 C << "\n#include <Ice/SliceChecksums.h>";
951 }
952
953 C << "\n#include <IceUtil/PopDisableWarnings.h>";
954
955 StringList includes = p->includeFiles();
956
957 for(StringList::const_iterator q = includes.begin(); q != includes.end(); ++q)
958 {
959 string extension = getHeaderExt((*q), p);
960 if(extension.empty())
961 {
962 extension = _headerExtension;
963 }
964 H << "\n#include <" << changeInclude(*q, _includePaths) << "." << extension << ">";
965 }
966
967 H << "\n#include <IceUtil/UndefSysMacros.h>";
968
969 //
970 // Emit #include statements for any cpp:include metadata directives
971 // in the top-level Slice file.
972 //
973 {
974 DefinitionContextPtr dc = p->findDefinitionContext(file);
975 assert(dc);
976 StringList globalMetaData = dc->getMetaData();
977 for(StringList::const_iterator q = globalMetaData.begin(); q != globalMetaData.end();)
978 {
979 string md = *q++;
980 static const string includePrefix = "cpp:include:";
981 if(md.find(includePrefix) == 0)
982 {
983 if(md.size() > includePrefix.size())
984 {
985 H << nl << "#include <" << md.substr(includePrefix.size()) << ">";
986 }
987 else
988 {
989 ostringstream ostr;
990 ostr << "ignoring invalid global metadata `" << md << "'";
991 dc->warning(InvalidMetaData, file, -1, ostr.str());
992 globalMetaData.remove(md);
993 }
994 }
995 }
996 dc->setMetaData(globalMetaData);
997 }
998
999 //
1000 // Disable shadow warnings in .cpp file
1001 //
1002 C << sp;
1003 C.zeroIndent();
1004 C << nl << "#if defined(_MSC_VER)";
1005 C << nl << "# pragma warning(disable:4458) // declaration of ... hides class member";
1006 C << nl << "#elif defined(__clang__)";
1007 C << nl << "# pragma clang diagnostic ignored \"-Wshadow\"";
1008 C << nl << "#elif defined(__GNUC__)";
1009 C << nl << "# pragma GCC diagnostic ignored \"-Wshadow\"";
1010 C << nl << "#endif";
1011
1012 printVersionCheck(H);
1013 printVersionCheck(C);
1014
1015 printDllExportStuff(H, _dllExport);
1016 if(_dllExport.size())
1017 {
1018 _dllExport += " ";
1019 }
1020
1021 H << sp;
1022 H.zeroIndent();
1023 H << nl << "#ifdef ICE_CPP11_MAPPING // C++11 mapping";
1024 H.restoreIndent();
1025
1026 C << sp;
1027 C.zeroIndent();
1028 C << nl << "#ifdef ICE_CPP11_MAPPING // C++11 mapping";
1029 C.restoreIndent();
1030 {
1031 normalizeMetaData(p, true);
1032
1033 Cpp11DeclVisitor declVisitor(H, C, _dllExport);
1034 p->visit(&declVisitor, false);
1035
1036 Cpp11TypesVisitor typesVisitor(H, C, _dllExport);
1037 p->visit(&typesVisitor, false);
1038
1039 Cpp11LocalObjectVisitor localObjectVisitor(H, C, _dllExport);
1040 p->visit(&localObjectVisitor, false);
1041
1042 Cpp11InterfaceVisitor interfaceVisitor(H, C, _dllExport);
1043 p->visit(&interfaceVisitor, false);
1044
1045 Cpp11ValueVisitor valueVisitor(H, C, _dllExport);
1046 p->visit(&valueVisitor, false);
1047
1048 Cpp11ProxyVisitor proxyVisitor(H, C, _dllExport);
1049 p->visit(&proxyVisitor, false);
1050
1051 Cpp11StreamVisitor streamVisitor(H, C, _dllExport);
1052 p->visit(&streamVisitor, false);
1053
1054 if(_implCpp11)
1055 {
1056 implH << "\n#include <";
1057 if(_include.size())
1058 {
1059 implH << _include << '/';
1060 }
1061 implH << _base << "." << _headerExtension << ">";
1062 writeExtraHeaders(implC);
1063
1064 implC << "\n#include <";
1065 if(_include.size())
1066 {
1067 implC << _include << '/';
1068 }
1069 implC << _base << "I." << _implHeaderExtension << ">";
1070
1071 Cpp11ImplVisitor implVisitor(implH, implC, _dllExport);
1072 p->visit(&implVisitor, false);
1073 }
1074
1075 Cpp11CompatibilityVisitor compatibilityVisitor(H, C, _dllExport);
1076 p->visit(&compatibilityVisitor, false);
1077
1078 generateChecksumMap(p);
1079 }
1080 H << sp;
1081 H.zeroIndent();
1082 H << nl << "#else // C++98 mapping";
1083 H.restoreIndent();
1084
1085 C << sp;
1086 C.zeroIndent();
1087 C << nl << "#else // C++98 mapping";
1088 C.restoreIndent();
1089 {
1090 normalizeMetaData(p, false);
1091
1092 ProxyDeclVisitor proxyDeclVisitor(H, C, _dllExport);
1093 p->visit(&proxyDeclVisitor, false);
1094
1095 ObjectDeclVisitor objectDeclVisitor(H, C, _dllExport);
1096 p->visit(&objectDeclVisitor, false);
1097
1098 TypesVisitor typesVisitor(H, C, _dllExport);
1099 p->visit(&typesVisitor, false);
1100
1101 AsyncVisitor asyncVisitor(H, C, _dllExport);
1102 p->visit(&asyncVisitor, false);
1103
1104 AsyncImplVisitor asyncImplVisitor(H, C, _dllExport);
1105 p->visit(&asyncImplVisitor, false);
1106
1107 //
1108 // The templates are emitted before the proxy definition
1109 // so the derivation hierarchy is known to the proxy:
1110 // the proxy relies on knowing the hierarchy to make the begin_
1111 // methods type-safe.
1112 //
1113 AsyncCallbackVisitor asyncCallbackVisitor(H, C, _dllExport);
1114 p->visit(&asyncCallbackVisitor, false);
1115
1116 ProxyVisitor proxyVisitor(H, C, _dllExport);
1117 p->visit(&proxyVisitor, false);
1118
1119 ObjectVisitor objectVisitor(H, C, _dllExport);
1120 p->visit(&objectVisitor, false);
1121
1122 StreamVisitor streamVisitor(H, C, _dllExport);
1123 p->visit(&streamVisitor, false);
1124
1125 //
1126 // We need to delay generating the template after the proxy
1127 // definition, because completed calls the begin_ method in the
1128 // proxy.
1129 //
1130 AsyncCallbackTemplateVisitor asyncCallbackTemplateVisitor(H, C, _dllExport);
1131 p->visit(&asyncCallbackTemplateVisitor, false);
1132
1133 if(_implCpp98)
1134 {
1135 implH << "\n#include <";
1136 if(_include.size())
1137 {
1138 implH << _include << '/';
1139 }
1140 implH << _base << "." << _headerExtension << ">";
1141
1142 writeExtraHeaders(implC);
1143
1144 implC << "\n#include <";
1145 if(_include.size())
1146 {
1147 implC << _include << '/';
1148 }
1149 implC << _base << "I." << _implHeaderExtension << ">";
1150
1151 ImplVisitor implVisitor(implH, implC, _dllExport);
1152 p->visit(&implVisitor, false);
1153 }
1154
1155 generateChecksumMap(p);
1156 }
1157
1158 H << sp;
1159 H.zeroIndent();
1160 H << nl << "#endif";
1161 H.restoreIndent();
1162
1163 C << sp;
1164 C.zeroIndent();
1165 C << nl << "#endif";
1166 C.restoreIndent();
1167 }
1168
1169 void
closeOutput()1170 Slice::Gen::closeOutput()
1171 {
1172 H.close();
1173 C.close();
1174 implH.close();
1175 implC.close();
1176 }
1177
1178 void
writeExtraHeaders(IceUtilInternal::Output & out)1179 Slice::Gen::writeExtraHeaders(IceUtilInternal::Output& out)
1180 {
1181 for(vector<string>::const_iterator i = _extraHeaders.begin(); i != _extraHeaders.end(); ++i)
1182 {
1183 string hdr = *i;
1184 string guard;
1185 string::size_type pos = hdr.rfind(',');
1186 if(pos != string::npos)
1187 {
1188 hdr = i->substr(0, pos);
1189 guard = i->substr(pos + 1);
1190 }
1191 if(!guard.empty())
1192 {
1193 out << "\n#ifndef " << guard;
1194 out << "\n#define " << guard;
1195 }
1196 out << "\n#include <";
1197 out << hdr << '>';
1198 if(!guard.empty())
1199 {
1200 out << "\n#endif";
1201 }
1202 }
1203 }
1204
TypesVisitor(Output & h,Output & c,const string & dllExport)1205 Slice::Gen::TypesVisitor::TypesVisitor(Output& h, Output& c, const string& dllExport) :
1206 H(h), C(c), _dllExport(dllExport), _doneStaticSymbol(false), _useWstring(false)
1207 {
1208 }
1209
1210 bool
visitModuleStart(const ModulePtr & p)1211 Slice::Gen::TypesVisitor::visitModuleStart(const ModulePtr& p)
1212 {
1213 if(!p->hasOtherConstructedOrExceptions())
1214 {
1215 return false;
1216 }
1217
1218 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
1219
1220 H << sp << nl << "namespace " << fixKwd(p->name()) << nl << '{';
1221
1222 return true;
1223 }
1224
1225 void
visitModuleEnd(const ModulePtr &)1226 Slice::Gen::TypesVisitor::visitModuleEnd(const ModulePtr&)
1227 {
1228 H << sp << nl << '}';
1229
1230 _useWstring = resetUseWstring(_useWstringHist);
1231 }
1232
1233 bool
visitClassDefStart(const ClassDefPtr &)1234 Slice::Gen::TypesVisitor::visitClassDefStart(const ClassDefPtr&)
1235 {
1236 return false;
1237 }
1238
1239 bool
visitExceptionStart(const ExceptionPtr & p)1240 Slice::Gen::TypesVisitor::visitExceptionStart(const ExceptionPtr& p)
1241 {
1242 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
1243
1244 string name = fixKwd(p->name());
1245 string scope = fixKwd(p->scope());
1246 string scoped = fixKwd(p->scoped());
1247 ExceptionPtr base = p->base();
1248 DataMemberList dataMembers = p->dataMembers();
1249 DataMemberList allDataMembers = p->allDataMembers();
1250 bool hasDefaultValues = p->hasDefaultValues();
1251
1252 vector<string> allParamDecls;
1253 vector<string> baseParams;
1254 map<string, CommentPtr> allComments;
1255
1256 string fileParam = "file";
1257 string lineParam = "line";
1258
1259 for(DataMemberList::const_iterator q = allDataMembers.begin(); q != allDataMembers.end(); ++q)
1260 {
1261 string typeName = inputTypeToString((*q)->type(), (*q)->optional(), scope, (*q)->getMetaData(), _useWstring);
1262 allParamDecls.push_back(typeName + " " + fixKwd((*q)->name()));
1263 CommentPtr comment = (*q)->parseComment(false);
1264 if(comment)
1265 {
1266 allComments[(*q)->name()] = comment;
1267 }
1268
1269 if((*q)->name() == "file")
1270 {
1271 fileParam = "file_";
1272 }
1273 else if((*q)->name() == "line")
1274 {
1275 fileParam = "line_";
1276 }
1277 }
1278
1279 if(base)
1280 {
1281 DataMemberList baseDataMembers = base->allDataMembers();
1282 for(DataMemberList::const_iterator q = baseDataMembers.begin(); q != baseDataMembers.end(); ++q)
1283 {
1284 baseParams.push_back(fixKwd((*q)->name()));
1285 }
1286 }
1287
1288 H << sp;
1289 writeDocSummary(H, p);
1290 H << nl << "class " << _dllExport << name << " : ";
1291 H.useCurrentPosAsIndent();
1292 H << "public ";
1293 if(base)
1294 {
1295 H << getUnqualified(fixKwd(base->scoped()), scope);
1296 }
1297 else
1298 {
1299 H << getUnqualified(p->isLocal() ? "::Ice::LocalException" : "::Ice::UserException", scope);
1300 }
1301 H.restoreIndent();
1302 H << sb;
1303
1304 H.dec();
1305 H << nl << "public:";
1306 H.inc();
1307
1308 H << sp;
1309 if(p->isLocal())
1310 {
1311 H << nl << "/**";
1312 H << nl << " * The file and line number are required for all local exceptions.";
1313 H << nl << " * @param " << fileParam
1314 << " The file name in which the exception was raised, typically __FILE__.";
1315 H << nl << " * @param " << lineParam
1316 << " The line number at which the exception was raised, typically __LINE__.";
1317 H << nl << " */";
1318 }
1319 else if(hasDefaultValues)
1320 {
1321 H << nl << "/** Default constructor that assigns default values to members as specified in the "
1322 "Slice definition. */";
1323 }
1324
1325 H << nl << name << spar;
1326 if(p->isLocal())
1327 {
1328 H << "const char* " + fileParam << "int " + lineParam;
1329 }
1330 H << epar;
1331 if(!p->isLocal() && !hasDefaultValues)
1332 {
1333 H << " {}";
1334 }
1335 else
1336 {
1337 H << ';';
1338 }
1339 if(!allParamDecls.empty())
1340 {
1341 H << nl << "/**";
1342 H << nl << " * One-shot constructor to initialize all data members.";
1343 if(p->isLocal())
1344 {
1345 H << nl << " * The file and line number are required for all local exceptions.";
1346 H << nl << " * @param " << fileParam
1347 << " The file name in which the exception was raised, typically __FILE__.";
1348 H << nl << " * @param " << lineParam
1349 << " The line number at which the exception was raised, typically __LINE__.";
1350 }
1351 for(DataMemberList::const_iterator q = allDataMembers.begin(); q != allDataMembers.end(); ++q)
1352 {
1353 map<string, CommentPtr>::iterator r = allComments.find((*q)->name());
1354 if(r != allComments.end())
1355 {
1356 H << nl << " * @param " << fixKwd(r->first) << " " << getDocSentence(r->second->overview());
1357 }
1358 }
1359 H << nl << " */";
1360 H << nl;
1361 if(!p->isLocal() && allParamDecls.size() == 1)
1362 {
1363 H << "explicit ";
1364 }
1365 H << name << spar;
1366 if(p->isLocal())
1367 {
1368 H << "const char* " + fileParam << "int " + lineParam;
1369 }
1370 H << allParamDecls << epar << ';';
1371 }
1372 H << nl << "virtual ~" << name << "() throw();";
1373 H << sp;
1374
1375 if(!p->isLocal())
1376 {
1377 string initName = "iceC" + p->flattenedScope() + p->name() + "_init";
1378
1379 C << sp << nl << "namespace";
1380 C << nl << "{";
1381
1382 C << sp << nl << "const ::IceInternal::DefaultUserExceptionFactoryInit< " << scoped << "> "
1383 << initName << "(\"" << p->scoped() << "\");";
1384
1385 C << sp << nl << "}";
1386 }
1387
1388 if(p->isLocal())
1389 {
1390 C << sp << nl << scoped.substr(2) << "::" << name << spar << "const char* " + fileParam
1391 << "int " + lineParam << epar << " :";
1392 C.inc();
1393 emitUpcall(base, "(" + fileParam + ", " + lineParam + ")", scope, true);
1394 if(p->hasDefaultValues())
1395 {
1396 C << ",";
1397 writeDataMemberInitializers(C, dataMembers, _useWstring);
1398 }
1399 C.dec();
1400 C << sb;
1401 C << eb;
1402 }
1403 else if(hasDefaultValues)
1404 {
1405 C << sp << nl << scoped.substr(2) << "::" << name << "() :";
1406 C.inc();
1407 writeDataMemberInitializers(C, dataMembers, _useWstring);
1408 C.dec();
1409 C << sb;
1410 C << eb;
1411 }
1412
1413 if(!allParamDecls.empty())
1414 {
1415 C << sp << nl;
1416 C << scoped.substr(2) << "::" << name << spar;
1417 if(p->isLocal())
1418 {
1419 C << "const char* " + fileParam << "int " + lineParam;
1420 }
1421 C << allParamDecls << epar;
1422 if(p->isLocal() || !baseParams.empty() || !dataMembers.empty())
1423 {
1424 C << " :";
1425 C.inc();
1426 string upcall;
1427 if(!allParamDecls.empty())
1428 {
1429 upcall = "(";
1430 if(p->isLocal())
1431 {
1432 upcall += fileParam + ", " + lineParam;
1433 }
1434 for(vector<string>::const_iterator pi = baseParams.begin(); pi != baseParams.end(); ++pi)
1435 {
1436 if(p->isLocal() || pi != baseParams.begin())
1437 {
1438 upcall += ", ";
1439 }
1440 upcall += *pi;
1441 }
1442 upcall += ")";
1443 }
1444 if(!dataMembers.empty())
1445 {
1446 upcall += ",";
1447 }
1448 emitUpcall(base, upcall, scope, p->isLocal());
1449 }
1450 for(DataMemberList::const_iterator d = dataMembers.begin(); d != dataMembers.end(); ++d)
1451 {
1452 if(d != dataMembers.begin())
1453 {
1454 C << ",";
1455 }
1456 string memberName = fixKwd((*d)->name());
1457 C << nl << memberName << "(" << memberName << ")";
1458 }
1459 if(p->isLocal() || !baseParams.empty() || !dataMembers.empty())
1460 {
1461 C.dec();
1462 }
1463 C << sb;
1464 C << eb;
1465 }
1466
1467 C << sp << nl;
1468 C << scoped.substr(2) << "::~" << name << "() throw()";
1469 C << sb;
1470 C << eb;
1471
1472 H << nl << "/**";
1473 H << nl << " * Obtains the Slice type ID of this exception.";
1474 H << nl << " * @return The fully-scoped type ID.";
1475 H << nl << " */";
1476 H << nl << "virtual ::std::string ice_id() const;";
1477 C << sp << nl << "::std::string" << nl << scoped.substr(2) << "::ice_id() const";
1478 C << sb;
1479 C << nl << "return \"" << p->scoped() << "\";";
1480 C << eb;
1481
1482 StringList metaData = p->getMetaData();
1483 if(find(metaData.begin(), metaData.end(), "cpp:ice_print") != metaData.end())
1484 {
1485 H << nl << "/**";
1486 H << nl << " * Prints this exception to the given stream.";
1487 H << nl << " * @param stream The target stream.";
1488 H << nl << " */";
1489 H << nl << "virtual void ice_print(::std::ostream& stream) const;";
1490 }
1491
1492 H << nl << "/**";
1493 H << nl << " * Polymporphically clones this exception.";
1494 H << nl << " * @return A shallow copy of this exception.";
1495 H << nl << " */";
1496 H << nl << "virtual " << name << "* ice_clone() const;";
1497 C << sp << nl << scoped.substr(2) << "*" << nl << scoped.substr(2) << "::ice_clone() const";
1498 C << sb;
1499 C << nl << "return new " << name << "(*this);";
1500 C << eb;
1501
1502 H << nl << "/**";
1503 H << nl << " * Throws this exception.";
1504 H << nl << " */";
1505 H << nl << "virtual void ice_throw() const;";
1506 C << sp << nl << "void" << nl << scoped.substr(2) << "::ice_throw() const";
1507 C << sb;
1508 C << nl << "throw *this;";
1509 C << eb;
1510
1511 if(!p->isLocal() && p->usesClasses(false))
1512 {
1513 if(!base || (base && !base->usesClasses(false)))
1514 {
1515 H << sp;
1516 H << nl << "/// \\cond STREAM";
1517 H << nl << "virtual bool _usesClasses() const;";
1518 H << nl << "/// \\endcond";
1519
1520 C << sp << nl << "bool";
1521 C << nl << scoped.substr(2) << "::_usesClasses() const";
1522 C << sb;
1523 C << nl << "return true;";
1524 C << eb;
1525 }
1526 }
1527
1528 if(!dataMembers.empty())
1529 {
1530 H << sp;
1531 }
1532 return true;
1533 }
1534
1535 void
visitExceptionEnd(const ExceptionPtr & p)1536 Slice::Gen::TypesVisitor::visitExceptionEnd(const ExceptionPtr& p)
1537 {
1538 string name = fixKwd(p->name());
1539 string scope = fixKwd(p->scope());
1540 string scoped = fixKwd(p->scoped());
1541 string factoryName;
1542
1543 if(!p->isLocal())
1544 {
1545 ExceptionPtr base = p->base();
1546 bool basePreserved = p->inheritsMetaData("preserve-slice");
1547 bool preserved = p->hasMetaData("preserve-slice");
1548
1549 if(preserved && !basePreserved)
1550 {
1551 H << sp;
1552 H << nl << "/**";
1553 H << nl << " * Obtains the SlicedData object created when an unknown exception type was marshaled";
1554 H << nl << " * in the sliced format and the Ice run time sliced it to a known type.";
1555 H << nl << " * @return The SlicedData object, or nil if the exception was not sliced or was not";
1556 H << nl << " * marshaled in the sliced format.";
1557 H << nl << " */";
1558 H << nl << "virtual ::Ice::SlicedDataPtr ice_getSlicedData() const;";
1559
1560 H << sp;
1561 H << nl << "/// \\cond STREAM";
1562 H << nl << "virtual void _write(::Ice::OutputStream*) const;";
1563 H << nl << "virtual void _read(::Ice::InputStream*);";
1564
1565 string baseName = base ? fixKwd(base->scoped()) : string("::Ice::UserException");
1566 H << nl << "using " << baseName << "::_write;";
1567 H << nl << "using " << baseName << "::_read;";
1568 H << nl << "/// \\endcond";
1569 }
1570
1571 H.dec();
1572 H << sp << nl << "protected:";
1573 H.inc();
1574
1575 H << sp;
1576 H << nl << "/// \\cond STREAM";
1577 H << nl << "virtual void _writeImpl(" << getUnqualified("::Ice::OutputStream*", scope) << ") const;";
1578 H << nl << "virtual void _readImpl(" << getUnqualified("::Ice::InputStream*", scope) << ");";
1579 H << nl << "/// \\endcond";
1580
1581 string baseName = getUnqualified(base ? fixKwd(base->scoped()) : "::Ice::UserException", scope);
1582
1583 if(preserved && !basePreserved)
1584 {
1585 H << sp;
1586 H << nl << "/// \\cond STREAM";
1587 H << nl << "::Ice::SlicedDataPtr _slicedData;";
1588 H << nl << "/// \\endcond";
1589
1590 C << sp;
1591 C << nl << "::Ice::SlicedDataPtr" << nl << scoped.substr(2) << "::ice_getSlicedData() const";
1592 C << sb;
1593 C << nl << "return _slicedData;";
1594 C << eb;
1595
1596 C << sp << nl << "void" << nl << scoped.substr(2) << "::_write("
1597 << getUnqualified("::Ice::OutputStream*", scope) << " ostr) const";
1598 C << sb;
1599 C << nl << "ostr->startException(_slicedData);";
1600 C << nl << "_writeImpl(ostr);";
1601 C << nl << "ostr->endException();";
1602 C << eb;
1603
1604 C << sp << nl << "void" << nl << scoped.substr(2) << "::_read("
1605 << getUnqualified("::Ice::InputStream*", scope) << " istr)";
1606 C << sb;
1607 C << nl << "istr->startException();";
1608 C << nl << "_readImpl(istr);";
1609 C << nl << "_slicedData = istr->endException(true);";
1610 C << eb;
1611 }
1612
1613 C << sp;
1614 C << nl << "/// \\cond STREAM";
1615 C << nl << "void" << nl << scoped.substr(2) << "::_writeImpl("
1616 << getUnqualified("::Ice::OutputStream*", scope) << " ostr) const";
1617 C << sb;
1618 C << nl << "ostr->startSlice(\"" << p->scoped() << "\", -1, " << (!base ? "true" : "false") << ");";
1619 C << nl << getUnqualified("::Ice::StreamWriter", scope) << "< " << name << ", "
1620 << getUnqualified("::Ice::OutputStream", scope) << ">::write(ostr, *this);";
1621 C << nl << "ostr->endSlice();";
1622 if(base)
1623 {
1624 emitUpcall(base, "::_writeImpl(ostr);", scope);
1625 }
1626 C << eb;
1627
1628 C << sp << nl << "void" << nl << scoped.substr(2) << "::_readImpl("
1629 << getUnqualified("::Ice::InputStream*", scope) << " istr)";
1630 C << sb;
1631 C << nl << "istr->startSlice();";
1632 C << nl << getUnqualified("::Ice::StreamReader", scope) << "< " << name << ", "
1633 << getUnqualified("::Ice::InputStream", scope) << ">::read(istr, *this);";
1634 C << nl << "istr->endSlice();";
1635 if(base)
1636 {
1637 emitUpcall(base, "::_readImpl(istr);", scope);
1638 }
1639 C << eb;
1640 C << nl << "/// \\endcond";
1641 }
1642 H << eb << ';';
1643
1644 if(!p->isLocal())
1645 {
1646 //
1647 // We need an instance here to trigger initialization if the implementation is in a static library.
1648 // But we do this only once per source file, because a single instance is sufficient to initialize
1649 // all of the globals in a compilation unit.
1650 //
1651 if(!_doneStaticSymbol)
1652 {
1653 _doneStaticSymbol = true;
1654 H << sp;
1655 H << nl << "/// \\cond INTERNAL";
1656 H << nl << "static " << name << " _iceS_" << p->name() << "_init;";
1657 H << nl << "/// \\endcond";
1658 }
1659 }
1660
1661 _useWstring = resetUseWstring(_useWstringHist);
1662 }
1663
1664 bool
visitStructStart(const StructPtr & p)1665 Slice::Gen::TypesVisitor::visitStructStart(const StructPtr& p)
1666 {
1667 DataMemberList dataMembers = p->dataMembers();
1668 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
1669 string scope = fixKwd(p->scope());
1670 string name = fixKwd(p->name());
1671
1672 H << sp;
1673 writeDocSummary(H, p);
1674
1675 bool classMetaData = findMetaData(p->getMetaData()) == "%class";
1676 if(classMetaData)
1677 {
1678 H << nl << "class " << name << " : public IceUtil::Shared";
1679 H << sb;
1680 H.dec();
1681 H << nl << "public:";
1682 H.inc();
1683 H << nl;
1684 if(p->hasDefaultValues())
1685 {
1686 H << nl << "/** Default constructor that assigns default values to members as specified in the "
1687 "Slice definition. */";
1688 H << nl << name << "() :";
1689 H.inc();
1690 writeDataMemberInitializers(H, dataMembers, _useWstring);
1691 H.dec();
1692 H << sb;
1693 H << eb;
1694 }
1695 else
1696 {
1697 H << nl << name << "() {}";
1698 }
1699 }
1700 else
1701 {
1702 H << nl << "struct " << name;
1703 H << sb;
1704 if(p->hasDefaultValues())
1705 {
1706 H << nl << "/** Default constructor that assigns default values to members as specified in the "
1707 "Slice definition. */";
1708 H << nl << name << "() :";
1709 H.inc();
1710 writeDataMemberInitializers(H, dataMembers, _useWstring);
1711 H.dec();
1712 H << sb;
1713 H << eb << nl;
1714 }
1715 }
1716
1717 //
1718 // Generate a one-shot constructor if the struct uses the class mapping, or if at least
1719 // one of its members has a default value.
1720 //
1721 if(!dataMembers.empty() && (findMetaData(p->getMetaData()) == "%class" || p->hasDefaultValues()))
1722 {
1723 vector<string> paramDecls;
1724 map<string, CommentPtr> comments;
1725 for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
1726 {
1727 string typeName =
1728 inputTypeToString((*q)->type(), (*q)->optional(), scope, (*q)->getMetaData(), _useWstring);
1729 paramDecls.push_back(typeName + " " + fixKwd((*q)->name()));
1730 CommentPtr comment = (*q)->parseComment(false);
1731 if(comment && !comment->overview().empty())
1732 {
1733 comments[(*q)->name()] = comment;
1734 }
1735 }
1736
1737 if(!comments.empty())
1738 {
1739 H << nl << "/**";
1740 H << nl << " * One-shot constructor to initialize all data members.";
1741 for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
1742 {
1743 map<string, CommentPtr>::iterator r = comments.find((*q)->name());
1744 if(r != comments.end())
1745 {
1746 H << nl << " * @param " << fixKwd(r->first) << " " << getDocSentence(r->second->overview());
1747 }
1748 }
1749 H << nl << " */";
1750 }
1751
1752 H << nl;
1753 if(paramDecls.size() == 1)
1754 {
1755 H << "explicit ";
1756 }
1757 H << fixKwd(p->name()) << spar << paramDecls << epar << " :";
1758 H.inc();
1759
1760 for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
1761 {
1762 if(q != dataMembers.begin())
1763 {
1764 H << ',';
1765 }
1766 string memberName = fixKwd((*q)->name());
1767 H << nl << memberName << '(' << memberName << ')';
1768 }
1769
1770 H.dec();
1771 H << sb;
1772 H << eb;
1773 H << nl;
1774 }
1775
1776 H << sp;
1777
1778 return true;
1779 }
1780
1781 void
visitStructEnd(const StructPtr & p)1782 Slice::Gen::TypesVisitor::visitStructEnd(const StructPtr& p)
1783 {
1784 string name = fixKwd(p->name());
1785 string scoped = fixKwd(p->scoped());
1786 string scope = fixKwd(p->scope());
1787
1788 DataMemberList dataMembers = p->dataMembers();
1789
1790 vector<string> params;
1791
1792 for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
1793 {
1794 params.push_back(fixKwd((*q)->name()));
1795 }
1796
1797 bool containsSequence = false;
1798 if((Dictionary::legalKeyType(p, containsSequence) && !containsSequence) || p->hasMetaData("cpp:comparable"))
1799 {
1800 H << sp << nl << "bool operator==(const " << name << "& rhs_) const";
1801 H << sb;
1802 H << nl << "if(this == &rhs_)";
1803 H << sb;
1804 H << nl << "return true;";
1805 H << eb;
1806 for(vector<string>::const_iterator pi = params.begin(); pi != params.end(); ++pi)
1807 {
1808 H << nl << "if(" << *pi << " != rhs_." << *pi << ')';
1809 H << sb;
1810 H << nl << "return false;";
1811 H << eb;
1812 }
1813 H << nl << "return true;";
1814 H << eb;
1815 H << sp << nl << "bool operator<(const " << name << "& rhs_) const";
1816 H << sb;
1817 H << nl << "if(this == &rhs_)";
1818 H << sb;
1819 H << nl << "return false;";
1820 H << eb;
1821 for(vector<string>::const_iterator pi = params.begin(); pi != params.end(); ++pi)
1822 {
1823 H << nl << "if(" << *pi << " < rhs_." << *pi << ')';
1824 H << sb;
1825 H << nl << "return true;";
1826 H << eb;
1827 H << nl << "else if(rhs_." << *pi << " < " << *pi << ')';
1828 H << sb;
1829 H << nl << "return false;";
1830 H << eb;
1831 }
1832 H << nl << "return false;";
1833 H << eb;
1834
1835 H << sp << nl << "bool operator!=(const " << name << "& rhs_) const";
1836 H << sb;
1837 H << nl << "return !operator==(rhs_);";
1838 H << eb;
1839 H << nl << "bool operator<=(const " << name << "& rhs_) const";
1840 H << sb;
1841 H << nl << "return operator<(rhs_) || operator==(rhs_);";
1842 H << eb;
1843 H << nl << "bool operator>(const " << name << "& rhs_) const";
1844 H << sb;
1845 H << nl << "return !operator<(rhs_) && !operator==(rhs_);";
1846 H << eb;
1847 H << nl << "bool operator>=(const " << name << "& rhs_) const";
1848 H << sb;
1849 H << nl << "return !operator<(rhs_);";
1850 H << eb;
1851 }
1852 H << eb << ';';
1853
1854 if(findMetaData(p->getMetaData()) == "%class")
1855 {
1856 H << sp << nl << "typedef ::IceUtil::Handle< " << scoped << "> " << p->name() + "Ptr;";
1857 }
1858
1859 _useWstring = resetUseWstring(_useWstringHist);
1860 }
1861
1862 void
visitDataMember(const DataMemberPtr & p)1863 Slice::Gen::TypesVisitor::visitDataMember(const DataMemberPtr& p)
1864 {
1865 ContainerPtr container = p->container();
1866 string name = fixKwd(p->name());
1867
1868 string scope = "";
1869 StructPtr st = StructPtr::dynamicCast(container);
1870 if(st)
1871 {
1872 scope = fixKwd(st->scope());
1873 }
1874
1875 ExceptionPtr ex = ExceptionPtr::dynamicCast(container);
1876 if(ex)
1877 {
1878 scope = fixKwd(ex->scope());
1879 }
1880
1881 writeDocSummary(H, p);
1882 H << nl << typeToString(p->type(), p->optional(), scope, p->getMetaData(), _useWstring) << ' ' << name << ';';
1883 }
1884
1885 void
visitSequence(const SequencePtr & p)1886 Slice::Gen::TypesVisitor::visitSequence(const SequencePtr& p)
1887 {
1888 string name = fixKwd(p->name());
1889 TypePtr type = p->type();
1890 ContainedPtr cont = ContainedPtr::dynamicCast(p->container());
1891 string scope = fixKwd(p->scope());
1892 string s = typeToString(type, scope, p->typeMetaData(), _useWstring);
1893 StringList metaData = p->getMetaData();
1894
1895 string seqType = findMetaData(metaData, _useWstring);
1896 H << sp;
1897
1898 writeDocSummary(H, p);
1899
1900 if(!seqType.empty())
1901 {
1902 H << nl << "typedef " << seqType << ' ' << name << ';';
1903 }
1904 else
1905 {
1906 H << nl << "typedef ::std::vector<" << (s[0] == ':' ? " " : "") << s << "> " << name << ';';
1907 }
1908 }
1909
1910 void
visitDictionary(const DictionaryPtr & p)1911 Slice::Gen::TypesVisitor::visitDictionary(const DictionaryPtr& p)
1912 {
1913 string name = fixKwd(p->name());
1914 ContainedPtr cont = ContainedPtr::dynamicCast(p->container());
1915 string scope = fixKwd(p->scope());
1916 string dictType = findMetaData(p->getMetaData());
1917
1918 H << sp;
1919 writeDocSummary(H, p);
1920
1921 if(dictType.empty())
1922 {
1923 //
1924 // A default std::map dictionary
1925 //
1926
1927 TypePtr keyType = p->keyType();
1928 TypePtr valueType = p->valueType();
1929 string ks = typeToString(keyType, scope, p->keyMetaData(), _useWstring);
1930 if(ks[0] == ':')
1931 {
1932 ks.insert(0, " ");
1933 }
1934 string vs = typeToString(valueType, scope, p->valueMetaData(), _useWstring);
1935
1936 H << nl << "typedef ::std::map<" << ks << ", " << vs << "> " << name << ';';
1937 }
1938 else
1939 {
1940 //
1941 // A custom dictionary
1942 //
1943 H << nl << "typedef " << dictType << ' ' << name << ';';
1944 }
1945 }
1946
1947 void
visitEnum(const EnumPtr & p)1948 Slice::Gen::TypesVisitor::visitEnum(const EnumPtr& p)
1949 {
1950 string name = fixKwd(p->name());
1951 EnumeratorList enumerators = p->enumerators();
1952
1953 string enumeratorPrefix = findMetaData(p->getMetaData()) == "%scoped" ? name : "";
1954
1955 //
1956 // Check if any of the enumerators were assigned an explicit value.
1957 //
1958 const bool explicitValue = p->explicitValue();
1959
1960 H << sp;
1961 writeDocSummary(H, p);
1962
1963 H << nl << "enum " << name;
1964 H << sb;
1965
1966 EnumeratorList::const_iterator en = enumerators.begin();
1967 while(en != enumerators.end())
1968 {
1969 writeDocSummary(H, *en);
1970 H << nl << fixKwd(enumeratorPrefix + (*en)->name());
1971 //
1972 // If any of the enumerators were assigned an explicit value, we emit
1973 // an explicit value for *all* enumerators.
1974 //
1975 if(explicitValue)
1976 {
1977 H << " = " << int64ToString((*en)->value());
1978 }
1979 if(++en != enumerators.end())
1980 {
1981 H << ',';
1982 }
1983 }
1984 H << eb << ';';
1985 }
1986
1987 void
visitConst(const ConstPtr & p)1988 Slice::Gen::TypesVisitor::visitConst(const ConstPtr& p)
1989 {
1990 string scope = fixKwd(p->scope());
1991 H << sp;
1992 writeDocSummary(H, p);
1993 H << nl << "const " << typeToString(p->type(), scope, p->typeMetaData(), _useWstring) << " " << fixKwd(p->name())
1994 << " = ";
1995 writeConstantValue(H, p->type(), p->valueType(), p->value(), _useWstring, p->typeMetaData(), scope);
1996 H << ';';
1997 }
1998
1999 void
emitUpcall(const ExceptionPtr & base,const string & call,const string & scope,bool isLocal)2000 Slice::Gen::TypesVisitor::emitUpcall(const ExceptionPtr& base, const string& call, const string& scope, bool isLocal)
2001 {
2002 C << nl;
2003 if(base)
2004 {
2005 C << getUnqualified(fixKwd(base->scoped()), scope);
2006 }
2007 else
2008 {
2009 C << getUnqualified(isLocal ? "::Ice::LocalException" : "::Ice::UserException", scope);
2010 }
2011 C << call;
2012 }
2013
ProxyDeclVisitor(Output & h,Output &,const string & dllExport)2014 Slice::Gen::ProxyDeclVisitor::ProxyDeclVisitor(Output& h, Output&, const string& dllExport) :
2015 H(h), _dllExport(dllExport)
2016 {
2017 }
2018
2019 bool
visitUnitStart(const UnitPtr & p)2020 Slice::Gen::ProxyDeclVisitor::visitUnitStart(const UnitPtr& p)
2021 {
2022 if(!p->hasNonLocalClassDecls())
2023 {
2024 return false;
2025 }
2026
2027 H << sp << nl << "namespace IceProxy" << nl << '{';
2028
2029 return true;
2030 }
2031
2032 void
visitUnitEnd(const UnitPtr &)2033 Slice::Gen::ProxyDeclVisitor::visitUnitEnd(const UnitPtr&)
2034 {
2035 H << sp << nl << '}';
2036 }
2037
2038 bool
visitModuleStart(const ModulePtr & p)2039 Slice::Gen::ProxyDeclVisitor::visitModuleStart(const ModulePtr& p)
2040 {
2041 if(!p->hasNonLocalClassDecls())
2042 {
2043 return false;
2044 }
2045
2046 string name = fixKwd(p->name());
2047
2048 H << sp << nl << "namespace " << name << nl << '{';
2049
2050 return true;
2051 }
2052
2053 void
visitModuleEnd(const ModulePtr &)2054 Slice::Gen::ProxyDeclVisitor::visitModuleEnd(const ModulePtr&)
2055 {
2056 H << sp << nl << '}';
2057 }
2058
2059 void
visitClassDecl(const ClassDeclPtr & p)2060 Slice::Gen::ProxyDeclVisitor::visitClassDecl(const ClassDeclPtr& p)
2061 {
2062 if(p->isLocal())
2063 {
2064 return;
2065 }
2066
2067 string name = fixKwd(p->name());
2068
2069 H << sp << nl << "class " << name << ';';
2070 //
2071 // Underscore prefix because it's a private function that should not clash with
2072 // an interface named 'readProxy'
2073 // Note that _readProxy is always in the IceProxy::... namespace
2074 //
2075 H << nl << "/// \\cond INTERNAL";
2076 H << nl << _dllExport << "void _readProxy(::Ice::InputStream*, ::IceInternal::ProxyHandle< " << name << ">&);";
2077 H << nl << _dllExport << "::IceProxy::Ice::Object* upCast(" << name << "*);";
2078 H << nl << "/// \\endcond";
2079 }
2080
ProxyVisitor(Output & h,Output & c,const string & dllExport)2081 Slice::Gen::ProxyVisitor::ProxyVisitor(Output& h, Output& c, const string& dllExport) :
2082 H(h), C(c), _dllExport(dllExport), _dllClassExport(toDllClassExport(dllExport)),
2083 _dllMemberExport(toDllMemberExport(dllExport)), _useWstring(false)
2084 {
2085 }
2086
2087 bool
visitUnitStart(const UnitPtr & p)2088 Slice::Gen::ProxyVisitor::visitUnitStart(const UnitPtr& p)
2089 {
2090 if(!p->hasNonLocalClassDefs())
2091 {
2092 return false;
2093 }
2094
2095 H << sp << nl << "namespace IceProxy" << nl << '{';
2096
2097 return true;
2098 }
2099
2100 void
visitUnitEnd(const UnitPtr &)2101 Slice::Gen::ProxyVisitor::visitUnitEnd(const UnitPtr&)
2102 {
2103 H << sp << nl << '}';
2104 }
2105
2106 bool
visitModuleStart(const ModulePtr & p)2107 Slice::Gen::ProxyVisitor::visitModuleStart(const ModulePtr& p)
2108 {
2109 if(!p->hasNonLocalClassDefs())
2110 {
2111 return false;
2112 }
2113
2114 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
2115
2116 string name = fixKwd(p->name());
2117
2118 H << sp << nl << "namespace " << name << nl << '{';
2119
2120 return true;
2121 }
2122
2123 void
visitModuleEnd(const ModulePtr &)2124 Slice::Gen::ProxyVisitor::visitModuleEnd(const ModulePtr&)
2125 {
2126 H << sp << nl << '}';
2127
2128 _useWstring = resetUseWstring(_useWstringHist);
2129 }
2130
2131 bool
visitClassDefStart(const ClassDefPtr & p)2132 Slice::Gen::ProxyVisitor::visitClassDefStart(const ClassDefPtr& p)
2133 {
2134 if(p->isLocal())
2135 {
2136 return false;
2137 }
2138
2139 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
2140
2141 string name = fixKwd(p->name());
2142 string scope = fixKwd(p->scope());
2143 string scoped = fixKwd(p->scoped());
2144 ClassList bases = p->bases();
2145
2146 if(bases.size() > 1)
2147 {
2148 //
2149 // Generated helper class to deal with multiple inheritance
2150 // when using Proxy template.
2151 //
2152
2153 string baseName = fixKwd("_" + p->name() + "Base");
2154
2155 H << sp;
2156 H << nl << "/// \\cond INTERNAL";
2157 H << nl << "class " << _dllClassExport << baseName << " : ";
2158 H.useCurrentPosAsIndent();
2159 for(ClassList::const_iterator q = bases.begin(); q != bases.end();)
2160 {
2161 H << "public virtual ::IceProxy" << fixKwd((*q)->scoped());
2162 if(++q != bases.end())
2163 {
2164 H << ", " << nl;
2165 }
2166 }
2167 H.restoreIndent();
2168 H << sb;
2169
2170 H.dec();
2171 H << nl << "public:";
2172 H.inc();
2173
2174 // Out of line dtor to avoid weak vtable
2175 H << sp << nl << _dllMemberExport << "virtual ~" << baseName << "();";
2176 C << sp;
2177 C << nl << "::IceProxy" << scope << baseName << "::~" << baseName << "()";
2178 C << sb;
2179 C << eb;
2180
2181 H.dec();
2182 H << sp << nl << "protected:";
2183 H.inc();
2184
2185 H << sp << nl << "virtual Object* _newInstance() const = 0;";
2186 H << eb << ';';
2187 H << nl << "/// \\endcond";
2188 }
2189
2190 H << sp << nl << "class " << _dllClassExport << name << " : ";
2191 H << "public virtual ::Ice::Proxy<" << name << ", ";
2192 if(bases.empty())
2193 {
2194 H << "::IceProxy::Ice::Object";
2195 }
2196 else if(bases.size() == 1)
2197 {
2198 H << "::IceProxy" << fixKwd(bases.front()->scoped());
2199 }
2200 else
2201 {
2202 H << fixKwd("_" + p->name() + "Base");
2203 }
2204 H << ">";
2205
2206 H << sb;
2207 H.dec();
2208 H << nl << "public:";
2209 H.inc();
2210
2211 C << sp;
2212 C << nl << "/// \\cond INTERNAL";
2213 C << nl
2214 << _dllExport
2215 << "::IceProxy::Ice::Object* ::IceProxy" << scope << "upCast(" << name << "* p) { return p; }";
2216
2217 C << sp;
2218 C << nl << "void" << nl << "::IceProxy" << scope << "_readProxy(::Ice::InputStream* istr, "
2219 << "::IceInternal::ProxyHandle< " << name << ">& v)";
2220 C << sb;
2221 C << nl << "::Ice::ObjectPrx proxy;";
2222 C << nl << "istr->read(proxy);";
2223 C << nl << "if(!proxy)";
2224 C << sb;
2225 C << nl << "v = 0;";
2226 C << eb;
2227 C << nl << "else";
2228 C << sb;
2229 C << nl << "v = new " << name << ';';
2230 C << nl << "v->_copyFrom(proxy);";
2231 C << eb;
2232 C << eb;
2233 C << nl << "/// \\endcond";
2234
2235 return true;
2236 }
2237
2238 void
visitClassDefEnd(const ClassDefPtr & p)2239 Slice::Gen::ProxyVisitor::visitClassDefEnd(const ClassDefPtr& p)
2240 {
2241 string name = fixKwd(p->name());
2242 string scoped = fixKwd(p->scoped());
2243 string scope = fixKwd(p->scope());
2244
2245 H << sp;
2246 H << nl << "/**";
2247 H << nl << " * Obtains the Slice type ID corresponding to this " << (p->isInterface() ? "interface" : "class")
2248 << ".";
2249 H << nl << " * @return A fully-scoped type ID.";
2250 H << nl << " */";
2251 H << nl << _dllMemberExport << "static const ::std::string& ice_staticId();";
2252
2253 H.dec();
2254 H << sp << nl << "protected:";
2255 H.inc();
2256 H << nl << "/// \\cond INTERNAL";
2257 H << sp << nl << _dllMemberExport << "virtual ::IceProxy::Ice::Object* _newInstance() const;";
2258 H << nl << "/// \\endcond";
2259 H << eb << ';';
2260
2261 C << sp;
2262 C << nl << "/// \\cond INTERNAL";
2263 C << nl << "::IceProxy::Ice::Object*";
2264 C << nl << "IceProxy" << scoped << "::_newInstance() const";
2265 C << sb;
2266 C << nl << "return new " << name << ";";
2267 C << eb;
2268 C << nl << "/// \\endcond";
2269
2270 C << sp;
2271 C << nl << "const ::std::string&" << nl << "IceProxy" << scoped << "::ice_staticId()";
2272 C << sb;
2273 C << nl << "return " << scoped << "::ice_staticId();";
2274 C << eb;
2275
2276 _useWstring = resetUseWstring(_useWstringHist);
2277 }
2278
2279 namespace
2280 {
2281
2282 bool
usePrivateEnd(const OperationPtr & p)2283 usePrivateEnd(const OperationPtr& p)
2284 {
2285 TypePtr ret = p->returnType();
2286 bool retIsOpt = p->returnIsOptional();
2287 string retSEnd = returnTypeToString(ret, retIsOpt, "", p->getMetaData(), TypeContextAMIEnd);
2288 string retSPrivateEnd = returnTypeToString(ret, retIsOpt, "", p->getMetaData(), TypeContextAMIPrivateEnd);
2289
2290 ParamDeclList outParams;
2291 vector<string> outDeclsEnd;
2292 vector<string> outDeclsPrivateEnd;
2293
2294 ParamDeclList paramList = p->parameters();
2295 for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
2296 {
2297 if((*q)->isOutParam())
2298 {
2299 outDeclsEnd.push_back(outputTypeToString((*q)->type(), (*q)->optional(), "", (*q)->getMetaData(),
2300 TypeContextAMIEnd));
2301 outDeclsPrivateEnd.push_back(outputTypeToString((*q)->type(), (*q)->optional(), "", (*q)->getMetaData(),
2302 TypeContextAMIPrivateEnd));
2303 }
2304 }
2305
2306 return retSEnd != retSPrivateEnd || outDeclsEnd != outDeclsPrivateEnd;
2307 }
2308
2309 }
2310
2311 void
visitOperation(const OperationPtr & p)2312 Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p)
2313 {
2314 string name = p->name();
2315 string flatName = "iceC" + p->flattenedScope() + p->name() + "_name";
2316 string scoped = fixKwd(p->scoped());
2317 string scope = fixKwd(p->scope());
2318
2319 TypePtr ret = p->returnType();
2320
2321 bool retIsOpt = p->returnIsOptional();
2322 string retS = returnTypeToString(ret, retIsOpt, "", p->getMetaData(), _useWstring | TypeContextAMIEnd);
2323 string retSEndAMI =
2324 returnTypeToString(ret, retIsOpt, "", p->getMetaData(), _useWstring | TypeContextAMIPrivateEnd);
2325 string retInS = retS != "void" ? inputTypeToString(ret, retIsOpt, "", p->getMetaData(), _useWstring) : "";
2326
2327 ContainerPtr container = p->container();
2328 ClassDefPtr cl = ClassDefPtr::dynamicCast(container);
2329 string clName = cl->name();
2330 string clScope = fixKwd(cl->scope());
2331 string delName = "Callback_" + clName + "_" + name;
2332 string delNameScoped = clScope + delName;
2333
2334 vector<string> paramsDecl;
2335 vector<string> args;
2336
2337 vector<string> paramsAMI;
2338 vector<string> paramsDeclAMI;
2339 vector<string> paramsDeclAMIBeginI;
2340 vector<string> argsAMI;
2341 vector<string> outParamsAMI;
2342 vector<string> outParamNamesAMI;
2343 vector<string> outParamsDeclAMI;
2344 vector<string> outParamsDeclImplAMI;
2345 vector<string> outParamsDeclEndAMI;
2346 vector<string> outDecls;
2347
2348 ParamDeclList paramList = p->parameters();
2349 ParamDeclList inParams = p->inParameters();
2350 ParamDeclList outParams = p->outParameters();
2351
2352 const string contextParam = escapeParam(paramList, "context");
2353 const string cbParam = escapeParam(inParams, "cb");
2354 const string cookieParam = escapeParam(paramList, "cookie");
2355 const string resultParam = escapeParam(outParams, "result");
2356
2357 vector<string> outEndArgs;
2358
2359 for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
2360 {
2361 string paramName = fixKwd((*q)->name());
2362
2363 StringList metaData = (*q)->getMetaData();
2364 string typeString;
2365 string typeStringEndAMI;
2366 if((*q)->isOutParam())
2367 {
2368 typeString =
2369 outputTypeToString((*q)->type(), (*q)->optional(), "", metaData, _useWstring | TypeContextAMIEnd);
2370 typeStringEndAMI = outputTypeToString((*q)->type(), (*q)->optional(), "", metaData,
2371 _useWstring | TypeContextAMIPrivateEnd);
2372 }
2373 else
2374 {
2375 typeString = inputTypeToString((*q)->type(), (*q)->optional(), "", metaData, _useWstring);
2376 }
2377
2378 paramsDecl.push_back(typeString + ' ' + paramName);
2379 args.push_back(paramName);
2380
2381 if(!(*q)->isOutParam())
2382 {
2383 paramsAMI.push_back(typeString);
2384 paramsDeclAMI.push_back(typeString + ' ' + paramName);
2385 paramsDeclAMIBeginI.push_back(typeString + ' ' + paramPrefix + (*q)->name());
2386 argsAMI.push_back(paramName);
2387 }
2388 else
2389 {
2390 outParamsAMI.push_back(typeString);
2391 outParamNamesAMI.push_back(paramName);
2392 outParamsDeclAMI.push_back(typeString + ' ' + paramName);
2393 outParamsDeclImplAMI.push_back(typeString + ' ' + paramPrefix + (*q)->name());
2394 outParamsDeclEndAMI.push_back(typeStringEndAMI + ' ' + paramPrefix + (*q)->name());
2395 outDecls.push_back(
2396 inputTypeToString((*q)->type(), (*q)->optional(), "", (*q)->getMetaData(), _useWstring));
2397 outEndArgs.push_back(getEndArg((*q)->type(), (*q)->getMetaData(), outParamNamesAMI.back()));
2398 }
2399 }
2400
2401 //
2402 // Check if we need to generate a private _iceI_end_ method. This is the case if the
2403 // when using certain mapping features such as cpp:array. While
2404 // the regular end_ method can't return pair<const TYPE*, const TYPE*> because the
2405 // pointers would be invalid once end_ returns, we still want to allow using this
2406 // alternate mapping with AMI response callbacks (to allow zero-copy for instance).
2407 // For this purpose, we generate a special _iceI_end method which is used by the
2408 // completed implementation of the generated Callback_Inft_opName operation
2409 // delegate.
2410 //
2411 bool generatePrivateEnd = retS != retSEndAMI || outParamsDeclAMI != outParamsDeclEndAMI;
2412 if(ret && generatePrivateEnd)
2413 {
2414 string typeStringEndAMI = outputTypeToString(ret, p->returnIsOptional(), "", p->getMetaData(),
2415 _useWstring | TypeContextAMIPrivateEnd);
2416 outParamsDeclEndAMI.push_back(typeStringEndAMI + ' ' + "ret");
2417 }
2418
2419 string thisPointer = fixKwd(scope.substr(0, scope.size() - 2)) + "*";
2420
2421 CommentPtr comment = p->parseComment(false);
2422 const string contextDoc = "@param " + contextParam + " The Context map to send with the invocation.";
2423 const string contextDecl = "const ::Ice::Context& " + contextParam + " = ::Ice::noExplicitContext";
2424 const string resultDoc = "The asynchronous result object for the invocation.";
2425 const string cbDoc = "@param " + cbParam + " Asynchronous callback object.";
2426 const string cookieDoc = "@param " + cookieParam + " User-defined data to associate with the invocation.";
2427 const string cookieDecl = "const ::Ice::LocalObjectPtr& " + cookieParam + " = 0";
2428
2429 const string deprecateSymbol = getDeprecateSymbol(p, cl);
2430 H << sp;
2431 if(comment)
2432 {
2433 StringList postParams;
2434 postParams.push_back(contextDoc);
2435 writeOpDocSummary(H, p, comment, OpDocAllParams, true, StringList(), postParams, comment->returns());
2436 }
2437 H << nl << deprecateSymbol << _dllMemberExport << retS << ' ' << fixKwd(name) << spar << paramsDecl
2438 << contextDecl << epar;
2439 H << sb << nl;
2440 if(ret)
2441 {
2442 H << "return ";
2443 }
2444 H << "end_" << name << spar << outParamNamesAMI << "_iceI_begin_" + name << spar << argsAMI;
2445 H << contextParam << "::IceInternal::dummyCallback" << "0" << "true" << epar << epar << ';';
2446 H << eb;
2447
2448 H << sp;
2449 if(comment)
2450 {
2451 StringList postParams, returns;
2452 postParams.push_back(contextDoc);
2453 returns.push_back(resultDoc);
2454 writeOpDocSummary(H, p, comment, OpDocInParams, false, StringList(), postParams, returns);
2455 }
2456 H << nl << "::Ice::AsyncResultPtr begin_" << name << spar << paramsDeclAMI << contextDecl << epar;
2457 H << sb;
2458 H << nl << "return _iceI_begin_" << name << spar << argsAMI << contextParam << "::IceInternal::dummyCallback"
2459 << "0"
2460 << epar << ';';
2461 H << eb;
2462
2463 H << sp;
2464 if(comment)
2465 {
2466 StringList postParams, returns;
2467 postParams.push_back(cbDoc);
2468 postParams.push_back(cookieDoc);
2469 returns.push_back(resultDoc);
2470 writeOpDocSummary(H, p, comment, OpDocInParams, false, StringList(), postParams, returns);
2471 }
2472 H << nl << "::Ice::AsyncResultPtr begin_" << name << spar << paramsDeclAMI
2473 << "const ::Ice::CallbackPtr& " + cbParam
2474 << cookieDecl << epar;
2475 H << sb;
2476 H << nl << "return _iceI_begin_" << name << spar << argsAMI << "::Ice::noExplicitContext" << cbParam << cookieParam
2477 << epar << ';';
2478 H << eb;
2479
2480 H << sp;
2481 if(comment)
2482 {
2483 StringList postParams, returns;
2484 postParams.push_back(contextDoc);
2485 postParams.push_back(cbDoc);
2486 postParams.push_back(cookieDoc);
2487 returns.push_back(resultDoc);
2488 writeOpDocSummary(H, p, comment, OpDocInParams, false, StringList(), postParams, returns);
2489 }
2490 H << nl << "::Ice::AsyncResultPtr begin_" << name << spar << paramsDeclAMI
2491 << "const ::Ice::Context& " + contextParam
2492 << "const ::Ice::CallbackPtr& " + cbParam
2493 << cookieDecl << epar;
2494 H << sb;
2495 H << nl << "return _iceI_begin_" << name << spar << argsAMI << contextParam << cbParam << cookieParam << epar
2496 << ';';
2497 H << eb;
2498
2499 H << sp;
2500 if(comment)
2501 {
2502 StringList postParams, returns;
2503 postParams.push_back(cbDoc);
2504 postParams.push_back(cookieDoc);
2505 returns.push_back(resultDoc);
2506 writeOpDocSummary(H, p, comment, OpDocInParams, false, StringList(), postParams, returns);
2507 }
2508 H << nl << "::Ice::AsyncResultPtr begin_" << name << spar << paramsDeclAMI
2509 << "const " + delNameScoped + "Ptr& " + cbParam
2510 << cookieDecl << epar;
2511 H << sb;
2512 H << nl << "return _iceI_begin_" << name << spar << argsAMI << "::Ice::noExplicitContext" << cbParam << cookieParam
2513 << epar << ';';
2514 H << eb;
2515
2516 H << sp;
2517 if(comment)
2518 {
2519 StringList postParams, returns;
2520 postParams.push_back(contextDoc);
2521 postParams.push_back(cbDoc);
2522 postParams.push_back(cookieDoc);
2523 returns.push_back(resultDoc);
2524 writeOpDocSummary(H, p, comment, OpDocInParams, false, StringList(), postParams, returns);
2525 }
2526 H << nl << "::Ice::AsyncResultPtr begin_" << name << spar << paramsDeclAMI
2527 << "const ::Ice::Context& " + contextParam
2528 << "const " + delNameScoped + "Ptr& " + cbParam
2529 << cookieDecl << epar;
2530 H << sb;
2531 H << nl << "return _iceI_begin_" << name << spar << argsAMI << contextParam << cbParam << cookieParam << epar
2532 << ';';
2533 H << eb;
2534
2535 H << sp;
2536 if(comment)
2537 {
2538 H << nl << "/**";
2539 H << nl << " * Completes an invocation of begin_" << name << ".";
2540 StringList postParams;
2541 postParams.push_back("@param " + resultParam + " " + resultDoc);
2542 writeOpDocParams(H, p, comment, OpDocOutParams, StringList(), postParams);
2543 if(!comment->returns().empty())
2544 {
2545 H << nl << " * @return ";
2546 writeDocLines(H, comment->returns(), false);
2547 }
2548 if(!comment->exceptions().empty())
2549 {
2550 writeOpDocExceptions(H, p, comment);
2551 }
2552 H << nl << " */";
2553 }
2554 H << nl << _dllMemberExport << retS << " end_" << name << spar << outParamsDeclAMI
2555 << "const ::Ice::AsyncResultPtr& " + resultParam << epar << ';';
2556 if(generatePrivateEnd)
2557 {
2558 H << nl << "/// \\cond INTERNAL";
2559 H << sp << nl << _dllMemberExport << "void _iceI_end_" << name << spar << outParamsDeclEndAMI;
2560 H << "const ::Ice::AsyncResultPtr&" << epar << ';';
2561 H << nl << "/// \\endcond";
2562 }
2563
2564 H.dec();
2565 H << nl;
2566 H << nl << "private:";
2567 H.inc();
2568 H << sp << nl << _dllMemberExport << "::Ice::AsyncResultPtr _iceI_begin_" << name << spar
2569 << paramsAMI << "const ::Ice::Context&"
2570 << "const ::IceInternal::CallbackBasePtr&"
2571 << "const ::Ice::LocalObjectPtr& cookie = 0"
2572 << "bool sync = false" << epar << ';';
2573 H.dec();
2574 H << nl;
2575 H << nl << "public:";
2576 H.inc();
2577
2578 C << sp << nl << "::Ice::AsyncResultPtr" << nl << "IceProxy" << scope << "_iceI_begin_" << name << spar
2579 << paramsDeclAMIBeginI
2580 << "const ::Ice::Context& context" << "const ::IceInternal::CallbackBasePtr& del"
2581 << "const ::Ice::LocalObjectPtr& cookie" << "bool sync" << epar;
2582 C << sb;
2583 if(p->returnsData())
2584 {
2585 C << nl << "_checkTwowayOnly(" << flatName << ", sync);";
2586 }
2587 C << nl << "::IceInternal::OutgoingAsyncPtr result = new ::IceInternal::CallbackOutgoing(this, " << flatName
2588 << ", del, cookie, sync);";
2589 C << nl << "try";
2590 C << sb;
2591 C << nl << "result->prepare(" << flatName << ", " << operationModeToString(p->sendMode()) << ", context);";
2592 if(inParams.empty())
2593 {
2594 C << nl << "result->writeEmptyParams();";
2595 }
2596 else
2597 {
2598 C << nl << "::Ice::OutputStream* ostr = result->startWriteParams(" << opFormatTypeToString(p, false) <<");";
2599 writeMarshalCode(C, inParams, 0, true, TypeContextInParam);
2600 if(p->sendsClasses(false))
2601 {
2602 C << nl << "ostr->writePendingValues();";
2603 }
2604 C << nl << "result->endWriteParams();";
2605 }
2606 C << nl << "result->invoke(" << flatName << ");";
2607 C << eb;
2608 C << nl << "catch(const ::Ice::Exception& ex)";
2609 C << sb;
2610 C << nl << "result->abort(ex);";
2611 C << eb;
2612 C << nl << "return result;";
2613 C << eb;
2614
2615 C << sp << nl << retS << nl << "IceProxy" << scope << "end_" << name << spar << outParamsDeclImplAMI
2616 << "const ::Ice::AsyncResultPtr& result" << epar;
2617 C << sb;
2618 if(p->returnsData())
2619 {
2620 C << nl << "::Ice::AsyncResult::_check(result, this, " << flatName << ");";
2621
2622 //
2623 // COMPILERFIX: It's necessary to generate the allocate code here before
2624 // this if(!result->wait()). If generated after this if block, we get
2625 // access violations errors with the test/Ice/slicing/objects test on VC9
2626 // and Windows 64 bits when compiled with optimization (see bug 4400).
2627 //
2628 writeAllocateCode(C, ParamDeclList(), p, true, "", _useWstring | TypeContextAMIEnd);
2629 C << nl << "if(!result->_waitForResponse())";
2630 C << sb;
2631 C << nl << "try";
2632 C << sb;
2633 C << nl << "result->_throwUserException();";
2634 C << eb;
2635 //
2636 // Generate a catch block for each legal user exception.
2637 //
2638 ExceptionList throws = p->throws();
2639 throws.sort();
2640 throws.unique();
2641 #if defined(__SUNPRO_CC)
2642 throws.sort(derivedToBaseCompare);
2643 #else
2644 throws.sort(Slice::DerivedToBaseCompare());
2645 #endif
2646 for(ExceptionList::const_iterator i = throws.begin(); i != throws.end(); ++i)
2647 {
2648 C << nl << "catch(const " << fixKwd((*i)->scoped()) << "&)";
2649 C << sb;
2650 C << nl << "throw;";
2651 C << eb;
2652 }
2653 C << nl << "catch(const ::Ice::UserException& ex)";
2654 C << sb;
2655 C << nl << "throw ::Ice::UnknownUserException(__FILE__, __LINE__, ex.ice_id());";
2656 C << eb;
2657 C << eb;
2658 if(ret || !outParams.empty())
2659 {
2660 C << nl << "::Ice::InputStream* istr = result->_startReadParams();";
2661 writeUnmarshalCode(C, outParams, p, true, _useWstring | TypeContextAMIEnd);
2662 if(p->returnsClasses(false))
2663 {
2664 C << nl << "istr->readPendingValues();";
2665 }
2666 C << nl << "result->_endReadParams();";
2667 }
2668 else
2669 {
2670 C << nl << "result->_readEmptyParams();";
2671 }
2672 if(ret)
2673 {
2674 C << nl << "return ret;";
2675 }
2676 }
2677 else
2678 {
2679 C << nl << "_end(result, " << flatName << ");";
2680 }
2681 C << eb;
2682
2683 if(generatePrivateEnd)
2684 {
2685 assert(p->returnsData());
2686
2687 C << sp << nl << "void IceProxy" << scope << "_iceI_end_" << name << spar << outParamsDeclEndAMI
2688 << "const ::Ice::AsyncResultPtr& result" << epar;
2689 C << sb;
2690 C << nl << "::Ice::AsyncResult::_check(result, this, " << flatName << ");";
2691 C << nl << "if(!result->_waitForResponse())";
2692 C << sb;
2693 C << nl << "try";
2694 C << sb;
2695 C << nl << "result->_throwUserException();";
2696 C << eb;
2697 //
2698 // Generate a catch block for each legal user exception.
2699 //
2700 ExceptionList throws = p->throws();
2701 throws.sort();
2702 throws.unique();
2703 #if defined(__SUNPRO_CC)
2704 throws.sort(derivedToBaseCompare);
2705 #else
2706 throws.sort(Slice::DerivedToBaseCompare());
2707 #endif
2708 for(ExceptionList::const_iterator i = throws.begin(); i != throws.end(); ++i)
2709 {
2710 C << nl << "catch(const " << fixKwd((*i)->scoped()) << "&)";
2711 C << sb;
2712 C << nl << "throw;";
2713 C << eb;
2714 }
2715 C << nl << "catch(const ::Ice::UserException& ex)";
2716 C << sb;
2717 C << nl << "throw ::Ice::UnknownUserException(__FILE__, __LINE__, ex.ice_id());";
2718 C << eb;
2719 C << eb;
2720
2721 if(ret || !outParams.empty())
2722 {
2723 C << nl << "::Ice::InputStream* istr = result->_startReadParams();";
2724 writeUnmarshalCode(C, outParams, p, true, _useWstring | TypeContextAMIPrivateEnd);
2725 if(p->returnsClasses(false))
2726 {
2727 C << nl << "istr->readPendingValues();";
2728 }
2729 C << nl << "result->_endReadParams();";
2730 }
2731 else
2732 {
2733 C << nl << "result->_readEmptyParams();";
2734 }
2735 C << eb;
2736 }
2737 }
2738
ObjectDeclVisitor(Output & h,Output & c,const string & dllExport)2739 Slice::Gen::ObjectDeclVisitor::ObjectDeclVisitor(Output& h, Output& c, const string& dllExport) :
2740 H(h), C(c), _dllExport(dllExport)
2741 {
2742 }
2743
2744 bool
visitModuleStart(const ModulePtr & p)2745 Slice::Gen::ObjectDeclVisitor::visitModuleStart(const ModulePtr& p)
2746 {
2747 if(!p->hasClassDecls())
2748 {
2749 return false;
2750 }
2751
2752 string name = fixKwd(p->name());
2753
2754 H << sp << nl << "namespace " << name << nl << '{';
2755 C << sp << nl << "namespace" << nl << "{";
2756 return true;
2757 }
2758
2759 void
visitModuleEnd(const ModulePtr &)2760 Slice::Gen::ObjectDeclVisitor::visitModuleEnd(const ModulePtr&)
2761 {
2762 H << sp << nl << '}';
2763 C << sp << nl << "}";
2764 }
2765
2766 void
visitClassDecl(const ClassDeclPtr & p)2767 Slice::Gen::ObjectDeclVisitor::visitClassDecl(const ClassDeclPtr& p)
2768 {
2769 string name = fixKwd(p->name());
2770 string scope = fixKwd(p->scope());
2771 string scoped = fixKwd(p->scoped());
2772
2773 H << sp << nl << "class " << name << ';';
2774 if(!p->isLocal())
2775 {
2776 //
2777 // upCast is not _upCast nor _iceUpCast for historical reasons. IceInternal::Handle
2778 // depends on this name
2779 //
2780 H << nl << "/// \\cond INTERNAL";
2781 H << nl << _dllExport << getUnqualified("::Ice::Object*", scope) << " upCast(" << name << "*);";
2782 H << nl << "/// \\endcond";
2783 H << nl << "typedef ::IceInternal::Handle< " << name << "> " << p->name() << "Ptr;";
2784 H << nl << "typedef ::IceInternal::ProxyHandle< ::IceProxy" << scoped << "> " << p->name() << "Prx;";
2785 H << nl << "typedef " << p->name() << "Prx " << p->name() << "PrxPtr;";
2786
2787 //
2788 // _ice prefix because this function is in the Slice module namespace, where the user
2789 // is allowed to define classes, functions etc. that start with _.
2790 //
2791 H << nl << "/// \\cond INTERNAL";
2792 H << nl << _dllExport << "void _icePatchObjectPtr(" << p->name() << "Ptr&, const "
2793 << getUnqualified("::Ice::ObjectPtr&", scope) << ");";
2794 H << nl << "/// \\endcond";
2795 }
2796 else
2797 {
2798 H << nl << "/// \\cond INTERNAL";
2799 H << nl << _dllExport << getUnqualified("::Ice::LocalObject*", scope) << " upCast("
2800 << getUnqualified(scoped, scope) << "*);";
2801 H << nl << "/// \\endcond";
2802 H << nl << "typedef ::IceInternal::Handle< " << name << "> " << p->name() << "Ptr;";
2803 }
2804 }
2805
2806 void
visitOperation(const OperationPtr & p)2807 Slice::Gen::ObjectDeclVisitor::visitOperation(const OperationPtr& p)
2808 {
2809 ClassDefPtr cl = ClassDefPtr::dynamicCast(p->container());
2810 if(cl && !cl->isLocal())
2811 {
2812 string flatName = "iceC" + p->flattenedScope() + p->name() + "_name";
2813 C << sp << nl << "const ::std::string " << flatName << " = \"" << p->name() << "\";";
2814 }
2815 }
2816
ObjectVisitor(Output & h,Output & c,const string & dllExport)2817 Slice::Gen::ObjectVisitor::ObjectVisitor(Output& h, Output& c, const string& dllExport) :
2818 H(h), C(c), _dllExport(dllExport), _doneStaticSymbol(false), _useWstring(false)
2819 {
2820 }
2821
2822 bool
visitModuleStart(const ModulePtr & p)2823 Slice::Gen::ObjectVisitor::visitModuleStart(const ModulePtr& p)
2824 {
2825 if(!p->hasClassDefs())
2826 {
2827 return false;
2828 }
2829
2830 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
2831
2832 string name = fixKwd(p->name());
2833
2834 H << sp << nl << "namespace " << name << nl << '{';
2835
2836 return true;
2837 }
2838
2839 void
visitModuleEnd(const ModulePtr &)2840 Slice::Gen::ObjectVisitor::visitModuleEnd(const ModulePtr&)
2841 {
2842 H << sp;
2843 H << nl << '}';
2844
2845 _useWstring = resetUseWstring(_useWstringHist);
2846 }
2847
2848 bool
visitClassDefStart(const ClassDefPtr & p)2849 Slice::Gen::ObjectVisitor::visitClassDefStart(const ClassDefPtr& p)
2850 {
2851 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
2852
2853 string name = fixKwd(p->name());
2854 string scope = fixKwd(p->scope());
2855 string scoped = fixKwd(p->scoped());
2856 ClassList bases = p->bases();
2857 ClassDefPtr base;
2858 if(!bases.empty() && !bases.front()->isInterface())
2859 {
2860 base = bases.front();
2861 }
2862 DataMemberList dataMembers = p->dataMembers();
2863 DataMemberList allDataMembers = p->allDataMembers();
2864 bool basePreserved = p->inheritsMetaData("preserve-slice");
2865 bool preserved = basePreserved || p->hasMetaData("preserve-slice");
2866
2867 H << sp;
2868 writeDocSummary(H, p);
2869 H << nl << "class " << _dllExport << name << " : ";
2870 H.useCurrentPosAsIndent();
2871 if(bases.empty())
2872 {
2873 H << "public virtual " << getUnqualified(p->isLocal() ? "::Ice::LocalObject" : "::Ice::Object", scope);
2874 }
2875 else
2876 {
2877 ClassList::const_iterator q = bases.begin();
2878 bool virtualInheritance = p->hasMetaData("cpp:virtual") || p->isInterface();
2879 while(q != bases.end())
2880 {
2881 if(virtualInheritance || (*q)->isInterface())
2882 {
2883 H << "virtual ";
2884 }
2885
2886 H << "public " << getUnqualified(fixKwd((*q)->scoped()), scope);
2887 if(++q != bases.end())
2888 {
2889 H << ',' << nl;
2890 }
2891 }
2892 }
2893
2894 bool hasBaseClass = !bases.empty() && !bases.front()->isInterface();
2895 bool override = !p->isLocal() && p->canBeCyclic() && (!hasBaseClass || !bases.front()->canBeCyclic());
2896 bool hasGCObjectBaseClass = basePreserved || override || preserved;
2897 if(!basePreserved && (override || preserved))
2898 {
2899 H << ", public ::IceInternal::GCObject";
2900 }
2901
2902 H.restoreIndent();
2903 H << sb;
2904 H.dec();
2905 H << nl << "public:" << sp;
2906 H.inc();
2907
2908 //
2909 // In C++, a nested type cannot have the same name as the enclosing type
2910 //
2911 if(!p->isLocal() && p->name() != "ProxyType")
2912 {
2913 H << nl << "typedef " << p->name() << "Prx ProxyType;";
2914 }
2915
2916 if(p->name() != "PointerType")
2917 {
2918 H << nl << "typedef " << p->name() << "Ptr PointerType;";
2919 }
2920
2921 H << sp << nl << "virtual ~" << name << "();";
2922 C << sp;
2923 C << nl << scoped.substr(2) << "::~" << name << "()";
2924 C << sb;
2925 C << eb;
2926
2927 vector<string> params;
2928 vector<string> allParamDecls;
2929
2930 for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
2931 {
2932 params.push_back(fixKwd((*q)->name()));
2933 }
2934
2935 for(DataMemberList::const_iterator q = allDataMembers.begin(); q != allDataMembers.end(); ++q)
2936 {
2937 string typeName = inputTypeToString((*q)->type(), (*q)->optional(), scope, (*q)->getMetaData(), _useWstring);
2938 allParamDecls.push_back(typeName + " " + fixKwd((*q)->name()));
2939 }
2940
2941 if(!p->isInterface())
2942 {
2943 if(p->hasDefaultValues())
2944 {
2945 H << sp;
2946 H << nl << "/** Default constructor that assigns default values to members as specified in the "
2947 "Slice definition. */";
2948 H << nl << name << "() :";
2949 H.inc();
2950 writeDataMemberInitializers(H, dataMembers, _useWstring);
2951 H.dec();
2952 H << sb;
2953 H << eb;
2954 }
2955 else
2956 {
2957 H << sp << nl << name << "()";
2958 H << sb << eb;
2959 }
2960
2961 emitOneShotConstructor(p);
2962 }
2963
2964 if(!p->isLocal())
2965 {
2966 C << sp;
2967 C << nl << "/// \\cond INTERNAL";
2968 C << nl
2969 << _dllExport
2970 << "::Ice::Object* " << scope.substr(2) << "upCast(" << name << "* p) { return p; }"
2971 << nl;
2972 C << nl << "/// \\endcond";
2973
2974 //
2975 // It would make sense to provide a covariant ice_clone(); unfortunately many compilers
2976 // (including VS2010) generate bad code for covariant types that use virtual inheritance
2977 //
2978
2979 if(!p->isInterface())
2980 {
2981 H << sp;
2982 H << nl << "/**";
2983 H << nl << " * Polymporphically clones this object.";
2984 H << nl << " * @return A shallow copy of this object.";
2985 H << nl << " */";
2986 H << nl << "virtual " << getUnqualified("::Ice::ObjectPtr", scope) << " ice_clone() const;";
2987
2988 if(hasGCObjectBaseClass)
2989 {
2990 C.zeroIndent();
2991 C << sp;
2992 C << nl << "#if defined(_MSC_VER) && (_MSC_VER >= 1900)";
2993 C << nl << "# pragma warning(push)";
2994 C << nl << "# pragma warning(disable:4589)";
2995 C << nl << "#endif";
2996 C.restoreIndent();
2997 }
2998 C << nl << "::Ice::ObjectPtr";
2999 C << nl << scoped.substr(2) << "::ice_clone() const";
3000 C << sb;
3001 if(!p->isAbstract())
3002 {
3003 C << nl << getUnqualified("::Ice::Object*", scope) << " p = new " << name << "(*this);";
3004 C << nl << "return p;";
3005 }
3006 else
3007 {
3008 //
3009 // We need this ice_clone for abstract classes derived from concrete classes
3010 //
3011 C << nl << "throw " << getUnqualified("::Ice::CloneNotImplementedException", scope)
3012 << "(__FILE__, __LINE__);";
3013 }
3014 C << eb;
3015 if(hasGCObjectBaseClass)
3016 {
3017 C.zeroIndent();
3018 C << nl << "#if defined(_MSC_VER) && (_MSC_VER >= 1900)";
3019 C << nl << "# pragma warning(pop)";
3020 C << nl << "#endif";
3021 C.restoreIndent();
3022 }
3023 }
3024
3025 ClassList allBases = p->allBases();
3026 StringList ids;
3027 transform(allBases.begin(), allBases.end(), back_inserter(ids), ::IceUtil::constMemFun(&Contained::scoped));
3028 StringList other;
3029 other.push_back(p->scoped());
3030 other.push_back("::Ice::Object");
3031 other.sort();
3032 ids.merge(other);
3033 ids.unique();
3034 StringList::const_iterator firstIter = ids.begin();
3035 StringList::const_iterator scopedIter = find(ids.begin(), ids.end(), p->scoped());
3036 assert(scopedIter != ids.end());
3037 StringList::difference_type scopedPos = IceUtilInternal::distance(firstIter, scopedIter);
3038
3039 H << sp;
3040 H << nl << "/**";
3041 H << nl << " * Determines whether this object supports an interface with the given Slice type ID.";
3042 H << nl << " * @param id The fully-scoped Slice type ID.";
3043 H << nl << " * @param current The Current object for the invocation.";
3044 H << nl << " * @return True if this object supports the interface, false, otherwise.";
3045 H << nl << " */";
3046 H << nl << "virtual bool ice_isA(const ::std::string& id, const " << getUnqualified("::Ice::Current&", scope)
3047 << " current = " << getUnqualified("::Ice::emptyCurrent", scope) << ") const;";
3048 H << sp;
3049 H << nl << "/**";
3050 H << nl << " * Obtains a list of the Slice type IDs representing the interfaces supported by this object.";
3051 H << nl << " * @param current The Current object for the invocation.";
3052 H << nl << " * @return A list of fully-scoped type IDs.";
3053 H << nl << " */";
3054 H << nl << "virtual ::std::vector< ::std::string> ice_ids(const " << getUnqualified("::Ice::Current&", scope)
3055 << " current = " << getUnqualified("::Ice::emptyCurrent", scope) << ") const;";
3056 H << sp;
3057 H << nl << "/**";
3058 H << nl << " * Obtains a Slice type ID representing the most-derived interface supported by this object.";
3059 H << nl << " * @param current The Current object for the invocation.";
3060 H << nl << " * @return A fully-scoped type ID.";
3061 H << nl << " */";
3062 H << nl << "virtual const ::std::string& ice_id(const " << getUnqualified("::Ice::Current&", scope)
3063 << " current = " << getUnqualified("::Ice::emptyCurrent", scope) << ") const;";
3064 H << sp;
3065 H << nl << "/**";
3066 H << nl << " * Obtains the Slice type ID corresponding to this class.";
3067 H << nl << " * @return A fully-scoped type ID.";
3068 H << nl << " */";
3069 H << nl << "static const ::std::string& ice_staticId();";
3070
3071 string flatName = "iceC" + p->flattenedScope() + p->name() + "_ids";
3072
3073 C << sp << nl << "namespace";
3074 C << nl << "{";
3075 C << nl << "const ::std::string " << flatName << '[' << ids.size() << "] =";
3076 C << sb;
3077
3078 for(StringList::const_iterator r = ids.begin(); r != ids.end();)
3079 {
3080 C << nl << '"' << *r << '"';
3081 if(++r != ids.end())
3082 {
3083 C << ',';
3084 }
3085 }
3086 C << eb << ';';
3087 C << sp << nl << "}";
3088
3089 C << sp;
3090 C << nl << "bool" << nl << scoped.substr(2)
3091 << "::ice_isA(const ::std::string& s, const " << getUnqualified("::Ice::Current&", scope) << ") const";
3092 C << sb;
3093 C << nl << "return ::std::binary_search(" << flatName << ", " << flatName << " + " << ids.size() << ", s);";
3094 C << eb;
3095
3096 C << sp;
3097 C << nl << "::std::vector< ::std::string>" << nl << scoped.substr(2)
3098 << "::ice_ids(const " << getUnqualified("::Ice::Current&", scope) << ") const";
3099 C << sb;
3100 C << nl << "return ::std::vector< ::std::string>(&" << flatName << "[0], &" << flatName
3101 << '[' << ids.size() << "]);";
3102 C << eb;
3103
3104 C << sp;
3105 C << nl << "const ::std::string&" << nl << scoped.substr(2)
3106 << "::ice_id(const " << getUnqualified("::Ice::Current&", scope) << ") const";
3107 C << sb;
3108 C << nl << "return ice_staticId();";
3109 C << eb;
3110
3111 C << sp;
3112 C << nl << "const ::std::string&" << nl << scoped.substr(2) << "::ice_staticId()";
3113 C << sb;
3114 C.zeroIndent();
3115 C << nl << "#ifdef ICE_HAS_THREAD_SAFE_LOCAL_STATIC";
3116 C.restoreIndent();
3117 C << nl << "static const ::std::string typeId = \"" << *scopedIter << "\";";
3118 C << nl << "return typeId;";
3119 C.zeroIndent();
3120 C << nl << "#else";
3121 C.restoreIndent();
3122 C << nl << "return " << flatName << '[' << scopedPos << "];";
3123 C.zeroIndent();
3124 C << nl << "#endif";
3125 C.restoreIndent();
3126 C << eb;
3127
3128 emitGCFunctions(p);
3129 }
3130 else
3131 {
3132 C << sp;
3133 C << nl << "/// \\cond INTERNAL";
3134 C << nl
3135 << _dllExport
3136 << "::Ice::LocalObject* " << scope.substr(2) << "upCast(" << getUnqualified(scoped, scope)
3137 << "* p) { return p; }";
3138 C << nl << "/// \\endcond";
3139 }
3140
3141 return true;
3142 }
3143
3144 void
visitClassDefEnd(const ClassDefPtr & p)3145 Slice::Gen::ObjectVisitor::visitClassDefEnd(const ClassDefPtr& p)
3146 {
3147 string name = fixKwd(p->name());
3148 string scoped = fixKwd(p->scoped());
3149 string scope = fixKwd(p->scope());
3150 ClassList bases = p->bases();
3151 ClassDefPtr base;
3152 if(!bases.empty() && !bases.front()->isInterface())
3153 {
3154 base = bases.front();
3155 }
3156 bool basePreserved = p->inheritsMetaData("preserve-slice");
3157 bool preserved = p->hasMetaData("preserve-slice");
3158
3159 bool inProtected = false;
3160
3161 if(!p->isLocal())
3162 {
3163 OperationList allOps = p->allOperations();
3164 if(!allOps.empty())
3165 {
3166 StringList allOpNames;
3167 transform(allOps.begin(), allOps.end(), back_inserter(allOpNames),
3168 ::IceUtil::constMemFun(&Contained::name));
3169
3170 allOpNames.push_back("ice_id");
3171 allOpNames.push_back("ice_ids");
3172 allOpNames.push_back("ice_isA");
3173 allOpNames.push_back("ice_ping");
3174 allOpNames.sort();
3175 allOpNames.unique();
3176
3177 H << sp;
3178 H << nl << "/// \\cond INTERNAL";
3179 H << nl << "virtual bool _iceDispatch(::IceInternal::Incoming&, const "
3180 << getUnqualified("::Ice::Current&", scope) << ");";
3181 H << nl << "/// \\endcond";
3182
3183 string flatName = "iceC" + p->flattenedScope() + p->name() + "_all";
3184 C << sp << nl << "namespace";
3185 C << nl << "{";
3186 C << nl << "const ::std::string " << flatName << "[] =";
3187 C << sb;
3188
3189 for(StringList::const_iterator q = allOpNames.begin(); q != allOpNames.end();)
3190 {
3191 C << nl << '"' << *q << '"';
3192 if(++q != allOpNames.end())
3193 {
3194 C << ',';
3195 }
3196 }
3197 C << eb << ';';
3198 C << sp << nl << "}";
3199 C << sp;
3200 C << nl << "/// \\cond INTERNAL";
3201 C << nl << "bool";
3202 C << nl << scoped.substr(2) << "::_iceDispatch(::IceInternal::Incoming& in, const "
3203 << getUnqualified("::Ice::Current&", scope) << " current)";
3204 C << sb;
3205
3206 C << nl << "::std::pair<const ::std::string*, const ::std::string*> r = "
3207 << "::std::equal_range(" << flatName << ", " << flatName << " + " << allOpNames.size()
3208 << ", current.operation);";
3209 C << nl << "if(r.first == r.second)";
3210 C << sb;
3211 C << nl << "throw " << getUnqualified("::Ice::OperationNotExistException", scope)
3212 << "(__FILE__, __LINE__, current.id, " << "current.facet, current.operation);";
3213 C << eb;
3214 C << sp;
3215 C << nl << "switch(r.first - " << flatName << ')';
3216 C << sb;
3217 int i = 0;
3218 for(StringList::const_iterator q = allOpNames.begin(); q != allOpNames.end(); ++q)
3219 {
3220 C << nl << "case " << i++ << ':';
3221 C << sb;
3222 C << nl << "return _iceD_" << *q << "(in, current);";
3223 C << eb;
3224 }
3225 C << nl << "default:";
3226 C << sb;
3227 C << nl << "assert(false);";
3228 C << nl << "throw " << getUnqualified("::Ice::OperationNotExistException", scope)
3229 << "(__FILE__, __LINE__, current.id, " << "current.facet, current.operation);";
3230 C << eb;
3231 C << eb;
3232 C << eb;
3233 C << nl << "/// \\endcond";
3234
3235 //
3236 // Check if we need to generate ice_operationAttributes()
3237 //
3238 map<string, int> attributesMap;
3239 for(OperationList::iterator r = allOps.begin(); r != allOps.end(); ++r)
3240 {
3241 int attributes = (*r)->attributes();
3242 if(attributes != 0)
3243 {
3244 attributesMap.insert(map<string, int>::value_type((*r)->name(), attributes));
3245 }
3246 }
3247
3248 if(!attributesMap.empty())
3249 {
3250 H << sp;
3251 H << nl << "/// \\cond INTERNAL";
3252 H << nl << "virtual " << getUnqualified("::Ice::Int", scope)
3253 << " ice_operationAttributes(const ::std::string&) const;";
3254 H << nl << "/// \\endcond";
3255
3256 string opAttrFlatName = "iceC" + p->flattenedScope() + p->name() + "_operationAttributes";
3257
3258 C << sp << nl << "namespace";
3259 C << nl << "{";
3260 C << nl << "const int " << opAttrFlatName << "[] = ";
3261 C << sb;
3262
3263 for(StringList::const_iterator q = allOpNames.begin(); q != allOpNames.end();)
3264 {
3265 int attributes = 0;
3266 string opName = *q;
3267 map<string, int>::iterator it = attributesMap.find(opName);
3268 if(it != attributesMap.end())
3269 {
3270 attributes = it->second;
3271 }
3272 C << nl << attributes;
3273
3274 if(++q != allOpNames.end())
3275 {
3276 C << ',';
3277 }
3278 C << " // " << opName;
3279 }
3280
3281 C << eb << ';';
3282 C << sp << nl << "}";
3283
3284 C << sp;
3285
3286 C << nl << "::Ice::Int" << nl << scoped.substr(2)
3287 << "::ice_operationAttributes(const ::std::string& opName) const";
3288 C << sb;
3289
3290 C << nl << "::std::pair<const ::std::string*, const ::std::string*> r = "
3291 << "::std::equal_range(" << flatName << ", " << flatName << " + " << allOpNames.size()
3292 << ", opName);";
3293 C << nl << "if(r.first == r.second)";
3294 C << sb;
3295 C << nl << "return -1;";
3296 C << eb;
3297
3298 C << nl << "return " << opAttrFlatName << "[r.first - " << flatName << "];";
3299 C << eb;
3300 }
3301 }
3302
3303 if(!p->isAbstract())
3304 {
3305 H << sp;
3306 H << nl << "/**";
3307 H << nl << " * Obtains a value factory that instantiates this class.";
3308 H << nl << " * @return The value factory.";
3309 H << nl << " */";
3310 H << nl << "static " << getUnqualified("::Ice::ValueFactoryPtr", scope) << " ice_factory();";
3311 }
3312
3313 if(preserved && !basePreserved)
3314 {
3315 H << sp;
3316 H << nl << "/**";
3317 H << nl << " * Obtains the SlicedData object created when an unknown class type was marshaled";
3318 H << nl << " * in the sliced format and the Ice run time sliced it to a known type.";
3319 H << nl << " * @return The SlicedData object, or nil if the class was not sliced or was not";
3320 H << nl << " * marshaled in the sliced format.";
3321 H << nl << " */";
3322 H << nl << "virtual " << getUnqualified("::Ice::SlicedDataPtr", scope) << " ice_getSlicedData() const;";
3323
3324 H << sp;
3325 H << nl << "/// \\cond STREAM";
3326 H << nl << "virtual void _iceWrite(" << getUnqualified("::Ice::OutputStream*", scope) << ") const;";
3327 H << nl << "virtual void _iceRead(" << getUnqualified("::Ice::InputStream*", scope) << ");";
3328 H << nl << "/// \\endcond";
3329 }
3330
3331 H.dec();
3332 H << sp << nl << "protected:";
3333 inProtected = true;
3334 H.inc();
3335
3336 H << sp;
3337 H << nl << "/// \\cond STREAM";
3338 H << nl << "virtual void _iceWriteImpl(" << getUnqualified("::Ice::OutputStream*", scope) << ") const;";
3339 H << nl << "virtual void _iceReadImpl(" << getUnqualified("::Ice::InputStream*", scope) << ");";
3340 H << nl << "/// \\endcond";
3341
3342 if(preserved && !basePreserved)
3343 {
3344 C << sp;
3345 C << nl << "::Ice::SlicedDataPtr" << nl << scoped.substr(2) << "::ice_getSlicedData() const";
3346 C << sb;
3347 C << nl << "return _iceSlicedData;";
3348 C << eb;
3349
3350 C << sp;
3351 C << nl << "void" << nl << scoped.substr(2) << "::_iceWrite(" << getUnqualified("::Ice::OutputStream*", scope)
3352 << "ostr) const";
3353 C << sb;
3354 C << nl << "ostr->startValue(_iceSlicedData);";
3355 C << nl << "_iceWriteImpl(ostr);";
3356 C << nl << "ostr->endValue();";
3357 C << eb;
3358
3359 C << sp;
3360 C << nl << "void" << nl << scoped.substr(2) << "::_iceRead(" << getUnqualified("::Ice::InputStream*", scope)
3361 << " istr)";
3362 C << sb;
3363 C << nl << "istr->startValue();";
3364 C << nl << "_iceReadImpl(istr);";
3365 C << nl << "_iceSlicedData = istr->endValue(true);";
3366 C << eb;
3367 }
3368
3369 C << sp;
3370 C << nl << "/// \\cond STREAM";
3371 C << nl << "void" << nl << scoped.substr(2) << "::_iceWriteImpl(" << getUnqualified("::Ice::OutputStream*", scope)
3372 << " ostr) const";
3373 C << sb;
3374 C << nl << "ostr->startSlice(ice_staticId(), " << p->compactId() << (!base ? ", true" : ", false") << ");";
3375 C << nl << getUnqualified("::Ice::StreamWriter", scope) << "< " << name << ", "
3376 << getUnqualified("::Ice::OutputStream", scope) << ">::write(ostr, *this);";
3377 C << nl << "ostr->endSlice();";
3378 if(base)
3379 {
3380 emitUpcall(base, "::_iceWriteImpl(ostr);", scope);
3381 }
3382 C << eb;
3383
3384 C << sp;
3385 C << nl << "void" << nl << scoped.substr(2) << "::_iceReadImpl(" << getUnqualified("::Ice::InputStream*", scope)
3386 << " istr)";
3387 C << sb;
3388 C << nl << "istr->startSlice();";
3389 C << nl << getUnqualified("::Ice::StreamReader", scope) << "< " << name << ", "
3390 << getUnqualified("::Ice::InputStream", scope) << ">::read(istr, *this);";
3391 C << nl << "istr->endSlice();";
3392 if(base)
3393 {
3394 emitUpcall(base, "::_iceReadImpl(istr);", scope);
3395 }
3396 C << eb;
3397 C << nl << "/// \\endcond";
3398
3399 if(!p->isAbstract() || p->compactId() >= 0)
3400 {
3401 C << sp << nl << "namespace";
3402 C << nl << "{";
3403
3404 if(!p->isAbstract())
3405 {
3406 string initName = "iceC" + p->flattenedScope() + p->name() + "_init";
3407 C << nl << "const ::IceInternal::DefaultValueFactoryInit< " << scoped << "> "
3408 << initName << "(\"" << p->scoped() << "\");";
3409 }
3410 if(p->compactId() >= 0)
3411 {
3412 string initName = "iceC" + p->flattenedScope() + p->name() + "_compactIdInit";
3413 C << nl << "const ::IceInternal::CompactIdInit "
3414 << initName << "(\"" << p->scoped() << "\", " << p->compactId() << ");";
3415 }
3416 C << nl << "}";
3417
3418 if(!p->isAbstract())
3419 {
3420 C << sp << nl << "::Ice::ValueFactoryPtr" << nl << scoped.substr(2) << "::ice_factory()";
3421 C << sb;
3422 C << nl << "return ::IceInternal::factoryTable->getValueFactory(" << scoped << "::ice_staticId());";
3423 C << eb;
3424 }
3425 }
3426 }
3427
3428 //
3429 // Emit data members. Access visibility may be specified by metadata.
3430 //
3431 bool generateFriend = false;
3432 DataMemberList dataMembers = p->dataMembers();
3433 bool prot = p->hasMetaData("protected");
3434 bool needSp = true;
3435 for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
3436 {
3437 if(prot || (*q)->hasMetaData("protected"))
3438 {
3439 if(!inProtected)
3440 {
3441 H.dec();
3442 H << sp << nl << "protected:" << sp;
3443 H.inc();
3444 inProtected = true;
3445 needSp = false;
3446 }
3447 generateFriend = true;
3448 }
3449 else
3450 {
3451 if(inProtected)
3452 {
3453 H.dec();
3454 H << sp << nl << "public:" << sp;
3455 H.inc();
3456 inProtected = false;
3457 needSp = false;
3458 }
3459 }
3460
3461 if(needSp)
3462 {
3463 H << sp;
3464 needSp = false;
3465 }
3466
3467 emitDataMember(*q);
3468 }
3469
3470 if(!p->isLocal() && preserved && !basePreserved)
3471 {
3472 if(!inProtected)
3473 {
3474 H.dec();
3475 H << sp << nl << "protected:";
3476 H.inc();
3477 inProtected = true;
3478 }
3479 H << sp;
3480 H << nl << "/// \\cond STREAM";
3481 H << nl << "::Ice::SlicedDataPtr _iceSlicedData;";
3482 H << nl << "/// \\endcond";
3483 }
3484
3485 if(generateFriend)
3486 {
3487 if(!inProtected)
3488 {
3489 H.dec();
3490 H << sp << nl << "protected:";
3491 H.inc();
3492 inProtected = true;
3493 }
3494
3495 H << sp;
3496 H << nl << "template<typename T, typename S>";
3497 H << nl << "friend struct Ice::StreamWriter;";
3498 H << nl << "template<typename T, typename S>";
3499 H << nl << "friend struct Ice::StreamReader;";
3500 }
3501
3502 H << eb << ';';
3503
3504 if(!p->isAbstract() && !p->isLocal() && !_doneStaticSymbol)
3505 {
3506 //
3507 // We need an instance here to trigger initialization if the implementation is in a static library.
3508 // But we do this only once per source file, because a single instance is sufficient to initialize
3509 // all of the globals in a compilation unit.
3510 //
3511 H << nl << "/// \\cond INTERNAL";
3512 H << nl << "static ::Ice::ValueFactoryPtr _iceS_" << p->name() << "_init = " << fixKwd(p->scoped())
3513 << "::ice_factory();";
3514 H << nl << "/// \\endcond";
3515 }
3516
3517 if(p->isLocal())
3518 {
3519 H << sp;
3520 H << nl << "/// \\cond INTERNAL";
3521 H << nl << "inline bool operator==(const " << fixKwd(p->name()) << "& lhs, const " << fixKwd(p->name())
3522 << "& rhs)";
3523 H << sb;
3524 H << nl << "return static_cast<const " << getUnqualified("::Ice::LocalObject&", scope)
3525 << ">(lhs) == static_cast<const " << getUnqualified("::Ice::LocalObject&", scope) << ">(rhs);";
3526 H << eb;
3527 H << sp;
3528 H << nl << "inline bool operator<(const " << fixKwd(p->name()) << "& lhs, const " << fixKwd(p->name())
3529 << "& rhs)";
3530 H << sb;
3531 H << nl << "return static_cast<const " << getUnqualified("::Ice::LocalObject&", scope)
3532 << ">(lhs) < static_cast<const " << getUnqualified("::Ice::LocalObject&", scope) << ">(rhs);";
3533 H << eb;
3534 H << nl << "/// \\endcond";
3535 }
3536 else
3537 {
3538 C << sp;
3539 C << nl << "/// \\cond INTERNAL";
3540 C << nl << "void";
3541 C << nl << scope.substr(2) << "_icePatchObjectPtr(" << p->name() << "Ptr& handle, const "
3542 << getUnqualified("::Ice::ObjectPtr&", scope) << " v)";
3543 C << sb;
3544 C << nl << "handle = " << p->name() << "Ptr::dynamicCast(v);";
3545 C << nl << "if(v && !handle)";
3546 C << sb;
3547 C << nl << "IceInternal::Ex::throwUOE(" << name << "::ice_staticId(), v);";
3548 C << eb;
3549 C << eb;
3550 C << nl << "/// \\endcond";
3551
3552 H << sp;
3553 H << nl << "/// \\cond INTERNAL";
3554 H << nl << "inline bool operator==(const " << fixKwd(p->name()) << "& lhs, const " << fixKwd(p->name())
3555 << "& rhs)";
3556 H << sb;
3557 H << nl << "return static_cast<const " << getUnqualified("::Ice::Object&", scope)
3558 << ">(lhs) == static_cast<const " << getUnqualified("::Ice::Object&", scope) << ">(rhs);";
3559 H << eb;
3560 H << sp;
3561 H << nl << "inline bool operator<(const " << fixKwd(p->name()) << "& lhs, const " << fixKwd(p->name())
3562 << "& rhs)";
3563 H << sb;
3564 H << nl << "return static_cast<const " << getUnqualified("::Ice::Object&", scope)
3565 << ">(lhs) < static_cast<const " << getUnqualified("::Ice::Object&", scope) << ">(rhs);";
3566 H << eb;
3567 H << nl << "/// \\endcond";
3568 }
3569
3570 _useWstring = resetUseWstring(_useWstringHist);
3571 }
3572
3573 bool
visitExceptionStart(const ExceptionPtr &)3574 Slice::Gen::ObjectVisitor::visitExceptionStart(const ExceptionPtr&)
3575 {
3576 return false;
3577 }
3578
3579 bool
visitStructStart(const StructPtr &)3580 Slice::Gen::ObjectVisitor::visitStructStart(const StructPtr&)
3581 {
3582 return false;
3583 }
3584
3585 void
visitOperation(const OperationPtr & p)3586 Slice::Gen::ObjectVisitor::visitOperation(const OperationPtr& p)
3587 {
3588 string name = p->name();
3589 string scoped = fixKwd(p->scoped());
3590 string scope = fixKwd(p->scope());
3591
3592 ContainerPtr container = p->container();
3593 ClassDefPtr cl = ClassDefPtr::dynamicCast(container);
3594 string classNameAMD = "AMD_" + cl->name();
3595 string classScope = fixKwd(cl->scope());
3596 string classScopedAMD = classScope + classNameAMD;
3597
3598 TypePtr ret = p->returnType();
3599 string retS = returnTypeToString(ret, p->returnIsOptional(), classScope, p->getMetaData(), _useWstring);
3600
3601 ParamDeclList inParams = p->inParameters();
3602 ParamDeclList outParams = p->outParameters();
3603 ParamDeclList paramList = p->parameters();
3604
3605 const string cbParam = escapeParam(paramList, "cb");
3606 const string cookieParam = escapeParam(paramList, "cookie");
3607 const string resultParam = escapeParam(outParams, "result");
3608 const string currentParam = escapeParam(paramList, "current");
3609
3610 string params = "(";
3611 string paramsDecl = "(";
3612 string args = "(";
3613
3614 string paramsAMD = "(const " + classScopedAMD + '_' + name + "Ptr& " + cbParam + ", ";
3615 string argsAMD = "(new IceAsync" + classScopedAMD + '_' + name + "(inS), ";
3616
3617 vector< string> outDecls;
3618 for(ParamDeclList::iterator q = paramList.begin(); q != paramList.end(); ++q)
3619 {
3620 string paramName = fixKwd((*q)->name());
3621 TypePtr type = (*q)->type();
3622 bool isOutParam = (*q)->isOutParam();
3623 string typeString;
3624 if(isOutParam)
3625 {
3626 typeString = outputTypeToString(type, (*q)->optional(), classScope, (*q)->getMetaData(), _useWstring);
3627 }
3628 else
3629 {
3630 typeString =
3631 inputTypeToString((*q)->type(), (*q)->optional(), classScope, (*q)->getMetaData(), _useWstring);
3632 }
3633
3634 if(q != paramList.begin())
3635 {
3636 params += ", ";
3637 paramsDecl += ", ";
3638 args += ", ";
3639 }
3640
3641 params += typeString;
3642 params += ' ';
3643 params += paramName;
3644 paramsDecl += typeString;
3645 paramsDecl += ' ';
3646 paramsDecl += paramName;
3647 args += paramPrefix + (*q)->name();
3648
3649 if(!isOutParam)
3650 {
3651 paramsAMD += typeString;
3652 paramsAMD += " ";
3653 paramsAMD += paramName;
3654 paramsAMD += ", ";
3655 argsAMD += paramPrefix + (*q)->name();
3656 argsAMD += ", ";
3657 }
3658 else
3659 {
3660 outDecls.push_back(inputTypeToString((*q)->type(), (*q)->optional(), classScope, (*q)->getMetaData(),
3661 _useWstring));
3662 }
3663 }
3664
3665 if(!cl->isLocal())
3666 {
3667 if(!paramList.empty())
3668 {
3669 params += ", ";
3670 paramsDecl += ", ";
3671 args += ", ";
3672 }
3673
3674 params += "const " + getUnqualified("::Ice::Current&", classScope) + " " + currentParam + " = " +
3675 getUnqualified("::Ice::emptyCurrent", classScope) + ")";
3676 paramsDecl += "const " + getUnqualified("::Ice::Current&", classScope) + " " + currentParam + ")";
3677 args += "current)";
3678 }
3679 else
3680 {
3681 params += ')';
3682 paramsDecl += ')';
3683 args += ')';
3684 }
3685
3686 paramsAMD += "const " + getUnqualified("::Ice::Current&", classScope) + " " + currentParam + " = " +
3687 getUnqualified("::Ice::emptyCurrent", classScope) + ")";
3688 argsAMD += "current)";
3689
3690 string isConst = ((p->mode() == Operation::Nonmutating) || p->hasMetaData("cpp:const")) ? " const" : "";
3691 string noExcept = (cl->isLocal() && p->hasMetaData("cpp:noexcept")) ? " ICE_NOEXCEPT" : "";
3692 bool amd = !cl->isLocal() && (cl->hasMetaData("amd") || p->hasMetaData("amd"));
3693
3694 string deprecateSymbol = getDeprecateSymbol(p, cl);
3695
3696 CommentPtr comment = p->parseComment(false);
3697 const string cbDoc = "@param " + cbParam + " The AMD callback object for the invocation.";
3698 const string currentDoc = "@param " + currentParam + " The Current object for the invocation.";
3699 const string cookieDoc = "@param " + cookieParam + " Extra data to associate with the invocation.";
3700 const string returnDoc = "The asynchronous result object for the invocation.";
3701
3702 H << sp;
3703 if(!amd)
3704 {
3705 if(comment)
3706 {
3707 StringList postParams;
3708 if(!cl->isLocal())
3709 {
3710 postParams.push_back(currentDoc);
3711 }
3712 writeOpDocSummary(H, p, comment, OpDocAllParams, true, StringList(), postParams, comment->returns());
3713 }
3714
3715 H << nl << deprecateSymbol
3716 << "virtual " << retS << ' ' << fixKwd(name) << params << isConst << noExcept << " = 0;";
3717 }
3718 else
3719 {
3720 if(comment)
3721 {
3722 StringList preParams, postParams;
3723 preParams.push_back(cbDoc);
3724 postParams.push_back(currentDoc);
3725 StringList noReturns; // Leave empty - the AMD method has a void return type.
3726 writeOpDocSummary(H, p, comment, OpDocInParams, true, preParams, postParams, noReturns);
3727 }
3728
3729 H << nl << deprecateSymbol
3730 << "virtual void " << name << "_async" << paramsAMD << isConst << noExcept << " = 0;";
3731 }
3732
3733 if(!cl->isLocal())
3734 {
3735 H << nl << "/// \\cond INTERNAL";
3736 H << nl << "bool _iceD_" << name << "(::IceInternal::Incoming&, const " << getUnqualified("::Ice::Current&", scope)
3737 << ")" << isConst << ';';
3738 H << nl << "/// \\endcond";
3739
3740 C << sp;
3741 //
3742 // inS, ret, current etc. may shadow class-with-operations data members in C++98
3743 //
3744 C << nl << "/// \\cond INTERNAL";
3745 C << nl << "bool" << nl << scope.substr(2) << "_iceD_" << name << "(::IceInternal::Incoming& inS"
3746 << ", const " << getUnqualified("::Ice::Current&", classScope) << " current)" << isConst;
3747 C << sb;
3748 C << nl << "_iceCheckMode(" << operationModeToString(p->mode()) << ", current.mode);";
3749
3750 if(!inParams.empty())
3751 {
3752 C << nl << getUnqualified("::Ice::InputStream*", classScope) << " istr = inS.startReadParams();";
3753 writeAllocateCode(C, inParams, 0, true, classScope, _useWstring | TypeContextInParam);
3754 writeUnmarshalCode(C, inParams, 0, true, TypeContextInParam);
3755 if(p->sendsClasses(false))
3756 {
3757 C << nl << "istr->readPendingValues();";
3758 }
3759 C << nl << "inS.endReadParams();";
3760 }
3761 else
3762 {
3763 C << nl << "inS.readEmptyParams();";
3764 }
3765 if(p->format() != DefaultFormat)
3766 {
3767 C << nl << "inS.setFormat(" << opFormatTypeToString(p, false) << ");";
3768 }
3769
3770 if(!amd)
3771 {
3772 writeAllocateCode(C, outParams, 0, true, classScope, _useWstring, "ret");
3773 C << nl;
3774 if(ret)
3775 {
3776 C << retS << " ret = ";
3777 }
3778 C << "this->" << fixKwd(name) << args << ';';
3779 if(ret || !outParams.empty())
3780 {
3781 C << nl << getUnqualified("::Ice::OutputStream*", classScope) << " ostr = inS.startWriteParams();";
3782 writeMarshalCode(C, outParams, p, true, 0);
3783 if(p->returnsClasses(false))
3784 {
3785 C << nl << "ostr->writePendingValues();";
3786 }
3787 C << nl << "inS.endWriteParams();";
3788 }
3789 else
3790 {
3791 C << nl << "inS.writeEmptyParams();";
3792 }
3793 C << nl << "return true;";
3794 }
3795 else
3796 {
3797 C << nl << "this->" << name << "_async" << argsAMD << ';';
3798 C << nl << "return false;";
3799 }
3800 C << eb;
3801 C << nl << "/// \\endcond";
3802 }
3803
3804 if(cl->isLocal() && (cl->hasMetaData("async-oneway") || p->hasMetaData("async-oneway")))
3805 {
3806 vector<string> paramsDeclAMI;
3807 vector<string> outParamsDeclAMI;
3808
3809 for(ParamDeclList::const_iterator r = paramList.begin(); r != paramList.end(); ++r)
3810 {
3811 string paramName = fixKwd((*r)->name());
3812
3813 StringList metaData = (*r)->getMetaData();
3814 string typeString;
3815 if((*r)->isOutParam())
3816 {
3817 typeString = outputTypeToString((*r)->type(), (*r)->optional(), classScope, metaData,
3818 _useWstring | TypeContextAMIEnd);
3819 }
3820 else
3821 {
3822 typeString = inputTypeToString((*r)->type(), (*r)->optional(), classScope, metaData, _useWstring);
3823 }
3824
3825 if(!(*r)->isOutParam())
3826 {
3827 paramsDeclAMI.push_back(typeString + ' ' + paramName);
3828 }
3829 else
3830 {
3831 outParamsDeclAMI.push_back(typeString + ' ' + paramName);
3832 }
3833 }
3834
3835 H << sp;
3836 if(comment)
3837 {
3838 StringList returns;
3839 returns.push_back(returnDoc);
3840 writeOpDocSummary(H, p, comment, OpDocInParams, false, StringList(), StringList(), returns);
3841 }
3842 H << nl << "virtual " << getUnqualified("::Ice::AsyncResultPtr", classScope) << " begin_" << name << spar
3843 << paramsDeclAMI << epar << " = 0;";
3844
3845 H << sp;
3846 if(comment)
3847 {
3848 StringList postParams, returns;
3849 postParams.push_back("@param " + cbParam + " Callback to be invoked when the invocation completes");
3850 postParams.push_back(cookieDoc);
3851 returns.push_back(returnDoc);
3852 writeOpDocSummary(H, p, comment, OpDocInParams, false, StringList(), postParams, returns);
3853 }
3854 H << nl << "virtual " << getUnqualified("::Ice::AsyncResultPtr", classScope) << " begin_" << name << spar
3855 << paramsDeclAMI
3856 << ("const " + getUnqualified("::Ice::CallbackPtr&", classScope) + " " + cbParam)
3857 << ("const " + getUnqualified("::Ice::LocalObjectPtr&", classScope) + " " + cookieParam + " = 0")
3858 << epar << " = 0;";
3859
3860 string delName = "Callback_" + cl->name() + "_" + name;
3861
3862 H << sp;
3863 if(comment)
3864 {
3865 StringList postParams, returns;
3866 postParams.push_back("@param " + cbParam + " Callback to be invoked when the invocation completes");
3867 postParams.push_back(cookieDoc);
3868 returns.push_back(returnDoc);
3869 writeOpDocSummary(H, p, comment, OpDocInParams, false, StringList(), postParams, returns);
3870 }
3871 H << nl << "virtual " << getUnqualified("::Ice::AsyncResultPtr", classScope) << " begin_" << name << spar
3872 << paramsDeclAMI
3873 << ("const " + delName + "Ptr& " + cbParam)
3874 << ("const " + getUnqualified("::Ice::LocalObjectPtr&", classScope) + " " + cookieParam + " = 0") << epar
3875 << " = 0;";
3876
3877 H << sp;
3878 if(comment)
3879 {
3880 StringList postParams, returns;
3881 postParams.push_back("@param " + resultParam +
3882 " The asynchronous result object returned by the begin_ method.");
3883 writeOpDocSummary(H, p, comment, OpDocOutParams, true, StringList(), postParams, comment->returns());
3884 }
3885 H << nl << "virtual " << retS << " end_" << name << spar << outParamsDeclAMI
3886 << ("const " + getUnqualified("::Ice::AsyncResultPtr&", classScope) + " " + resultParam) << epar << " = 0;";
3887 }
3888 }
3889
3890 void
emitDataMember(const DataMemberPtr & p)3891 Slice::Gen::ObjectVisitor::emitDataMember(const DataMemberPtr& p)
3892 {
3893 string name = fixKwd(p->name());
3894 ContainerPtr container = p->container();
3895 ClassDefPtr cl = ClassDefPtr::dynamicCast(container);
3896 int typeContext = cl->isLocal() ? TypeContextLocal | _useWstring : _useWstring;
3897 writeDocSummary(H, p);
3898 H << nl << typeToString(p->type(), p->optional(), fixKwd(cl->scope()), p->getMetaData(), typeContext) << ' '
3899 << name << ';';
3900 }
3901
3902 void
emitGCFunctions(const ClassDefPtr & p)3903 Slice::Gen::ObjectVisitor::emitGCFunctions(const ClassDefPtr& p)
3904 {
3905 string scoped = fixKwd(p->scoped());
3906 string scope = fixKwd(p->scope());
3907 ClassList bases = p->bases();
3908 ClassDefPtr base;
3909 if(!bases.empty() && !bases.front()->isInterface())
3910 {
3911 base = bases.front();
3912 }
3913 DataMemberList dataMembers = p->dataMembers();
3914
3915 //
3916 // A class can potentially be part of a cycle if it (recursively) contains class
3917 // members.
3918 //
3919 bool canBeCyclic = p->canBeCyclic();
3920 bool basePreserved = p->inheritsMetaData("preserve-slice");
3921 bool preserved = basePreserved || p->hasMetaData("preserve-slice");
3922
3923 //
3924 // _iceGcVisit() is overridden by the basemost class that can be
3925 // cyclic, plus all classes derived from that class.
3926 //
3927 // We also override these methods for the initial preserved class in a
3928 // hierarchy, regardless of whether the class itself is cyclic.
3929 //
3930 if(canBeCyclic || (preserved && !basePreserved))
3931 {
3932 H << nl << "/// \\cond INTERNAL";
3933 H << nl << "virtual void _iceGcVisitMembers(::IceInternal::GCVisitor&);";
3934 H << nl << "/// \\endcond";
3935
3936 C << sp << nl << "void" << nl << scoped.substr(2) << "::_iceGcVisitMembers(::IceInternal::GCVisitor& v_)";
3937 C << sb;
3938
3939 bool hasCyclicBase = base && base->canBeCyclic();
3940 if(hasCyclicBase || basePreserved)
3941 {
3942 emitUpcall(bases.front(), "::_iceGcVisitMembers(v_);", scope);
3943 }
3944
3945 if(preserved && !basePreserved)
3946 {
3947 C << nl << "if(_iceSlicedData)";
3948 C << sb;
3949 C << nl << "_iceSlicedData->_iceGcVisitMembers(v_);";
3950 C << eb;
3951 }
3952
3953 for(DataMemberList::const_iterator i = dataMembers.begin(); i != dataMembers.end(); ++i)
3954 {
3955 if((*i)->type()->usesClasses())
3956 {
3957 if((*i)->optional())
3958 {
3959 C << nl << "if(" << fixKwd((*i)->name()) << ')';
3960 C << sb;
3961 emitGCVisitCode((*i)->type(), getDataMemberRef(*i), "", 0);
3962 C << eb;
3963 }
3964 else
3965 {
3966 emitGCVisitCode((*i)->type(), getDataMemberRef(*i), "", 0);
3967 }
3968 }
3969 }
3970 C << eb;
3971 }
3972 }
3973
3974 void
emitGCVisitCode(const TypePtr & p,const string & prefix,const string & name,int level)3975 Slice::Gen::ObjectVisitor::emitGCVisitCode(const TypePtr& p, const string& prefix, const string& name, int level)
3976 {
3977 BuiltinPtr builtin = BuiltinPtr::dynamicCast(p);
3978 if((builtin &&
3979 (BuiltinPtr::dynamicCast(p)->kind() == Builtin::KindObject || BuiltinPtr::dynamicCast(p)->kind() == Builtin::KindValue)) ||
3980 ClassDeclPtr::dynamicCast(p))
3981 {
3982 C << nl << "if(" << prefix << name << ')';
3983 C << sb;
3984 ClassDeclPtr decl = ClassDeclPtr::dynamicCast(p);
3985 if(decl)
3986 {
3987 string scope = fixKwd(decl->scope());
3988 C << nl << "if((" << scope << "upCast(" << prefix << name << ".get())->_iceGcVisit(v_)))";
3989 }
3990 else
3991 {
3992 C << nl << "if((" << prefix << name << ".get())->_iceGcVisit(v_))";
3993 }
3994 C << sb;
3995 C << nl << prefix << name << " = 0;";
3996 C << eb;
3997 C << eb;
3998 }
3999 else if(StructPtr::dynamicCast(p))
4000 {
4001 StructPtr s = StructPtr::dynamicCast(p);
4002 DataMemberList dml = s->dataMembers();
4003 for(DataMemberList::const_iterator i = dml.begin(); i != dml.end(); ++i)
4004 {
4005 if((*i)->type()->usesClasses())
4006 {
4007 emitGCVisitCode((*i)->type(), prefix + name + ".", fixKwd((*i)->name()), ++level);
4008 }
4009 }
4010 }
4011 else if(DictionaryPtr::dynamicCast(p))
4012 {
4013 DictionaryPtr d = DictionaryPtr::dynamicCast(p);
4014 string scoped = fixKwd(d->scoped());
4015 ostringstream tmp;
4016 tmp << "_i" << level;
4017 string iterName = tmp.str();
4018 C << sb;
4019 C << nl << "for(" << scoped << "::iterator " << iterName << " = " << prefix + name
4020 << ".begin(); " << iterName << " != " << prefix + name << ".end(); ++" << iterName << ")";
4021 C << sb;
4022 emitGCVisitCode(d->valueType(), "", string("(*") + iterName + ").second", ++level);
4023 C << eb;
4024 C << eb;
4025 }
4026 else if(SequencePtr::dynamicCast(p))
4027 {
4028 SequencePtr s = SequencePtr::dynamicCast(p);
4029 string scoped = fixKwd(s->scoped());
4030 ostringstream tmp;
4031 tmp << "_i" << level;
4032 string iterName = tmp.str();
4033 C << sb;
4034 C << nl << "for(" << scoped << "::iterator " << iterName << " = " << prefix + name
4035 << ".begin(); " << iterName << " != " << prefix + name << ".end(); ++" << iterName << ")";
4036 C << sb;
4037 emitGCVisitCode(s->type(), string("(*") + iterName + ")", "", ++level);
4038 C << eb;
4039 C << eb;
4040 }
4041 }
4042
4043 bool
emitVirtualBaseInitializers(const ClassDefPtr & p,bool virtualInheritance,bool direct)4044 Slice::Gen::ObjectVisitor::emitVirtualBaseInitializers(const ClassDefPtr& p, bool virtualInheritance, bool direct)
4045 {
4046 DataMemberList allDataMembers = p->allDataMembers();
4047 if(allDataMembers.empty())
4048 {
4049 return false;
4050 }
4051
4052 ClassList bases = p->bases();
4053 if(!bases.empty() && !bases.front()->isInterface())
4054 {
4055 if(emitVirtualBaseInitializers(bases.front(), p->hasMetaData("cpp:virtual"), false))
4056 {
4057 H << ',';
4058 }
4059 }
4060
4061 //
4062 // Do not call non direct base classes constructor if not using virtual inheritance.
4063 //
4064 if(!direct && !virtualInheritance)
4065 {
4066 return false;
4067 }
4068
4069 string upcall = "(";
4070 for(DataMemberList::const_iterator q = allDataMembers.begin(); q != allDataMembers.end(); ++q)
4071 {
4072 if(q != allDataMembers.begin())
4073 {
4074 upcall += ", ";
4075 }
4076 upcall += fixKwd((*q)->name());
4077 }
4078 upcall += ")";
4079
4080 H << nl << fixKwd(p->scoped()) << upcall;
4081
4082 return true;
4083 }
4084
4085 void
emitOneShotConstructor(const ClassDefPtr & p)4086 Slice::Gen::ObjectVisitor::emitOneShotConstructor(const ClassDefPtr& p)
4087 {
4088 DataMemberList allDataMembers = p->allDataMembers();
4089 string scope = fixKwd(p->scope());
4090
4091 if(!allDataMembers.empty())
4092 {
4093 vector<string> allParamDecls;
4094 map<string, CommentPtr> allComments;
4095
4096 bool virtualInheritance = p->hasMetaData("cpp:virtual");
4097 bool callBaseConstructors = !(p->isAbstract() && virtualInheritance);
4098 DataMemberList dataMembers = p->dataMembers();
4099
4100 int typeContext = p->isLocal() ? (_useWstring | TypeContextLocal) : _useWstring;
4101
4102 for(DataMemberList::const_iterator q = allDataMembers.begin(); q != allDataMembers.end(); ++q)
4103 {
4104 string typeName =
4105 inputTypeToString((*q)->type(), (*q)->optional(), scope, (*q)->getMetaData(), typeContext);
4106 bool dataMember = std::find(dataMembers.begin(), dataMembers.end(), (*q)) != dataMembers.end();
4107 allParamDecls.push_back(typeName + ((dataMember || callBaseConstructors) ?
4108 (" " + fixKwd((*q)->name())) :
4109 (" /*" + fixKwd((*q)->name()) + "*/")));
4110 CommentPtr comment = (*q)->parseComment(false);
4111 if(comment)
4112 {
4113 allComments[(*q)->name()] = comment;
4114 }
4115 }
4116
4117 H << sp;
4118 H << nl << "/**";
4119 H << nl << " * One-shot constructor to initialize all data members.";
4120 for(DataMemberList::const_iterator q = allDataMembers.begin(); q != allDataMembers.end(); ++q)
4121 {
4122 map<string, CommentPtr>::iterator r = allComments.find((*q)->name());
4123 if(r != allComments.end())
4124 {
4125 H << nl << " * @param " << fixKwd(r->first) << " " << getDocSentence(r->second->overview());
4126 }
4127 }
4128 H << nl << " */";
4129 H << nl;
4130 if(allParamDecls.size() == 1)
4131 {
4132 H << "explicit ";
4133 }
4134 H << fixKwd(p->name()) << spar << allParamDecls << epar;
4135 if(callBaseConstructors || !dataMembers.empty())
4136 {
4137 H << " :";
4138 }
4139 H.inc();
4140
4141 ClassList bases = p->bases();
4142 ClassDefPtr base;
4143
4144 if(!bases.empty() && !bases.front()->isInterface() && callBaseConstructors)
4145 {
4146 if(emitVirtualBaseInitializers(bases.front(), virtualInheritance, true))
4147 {
4148 if(!dataMembers.empty())
4149 {
4150 H << ',';
4151 }
4152 }
4153 }
4154
4155 if(!dataMembers.empty())
4156 {
4157 H << nl;
4158 }
4159 for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
4160 {
4161 if(q != dataMembers.begin())
4162 {
4163 H << ',' << nl;
4164 }
4165 string memberName = fixKwd((*q)->name());
4166 H << memberName << '(' << memberName << ')';
4167 }
4168
4169 H.dec();
4170 H << sb;
4171 H << eb;
4172 }
4173 }
4174
4175 void
emitUpcall(const ClassDefPtr & base,const string & call,const string & scope)4176 Slice::Gen::ObjectVisitor::emitUpcall(const ClassDefPtr& base, const string& call, const string& scope)
4177 {
4178 C << nl;
4179 if(base)
4180 {
4181 C << getUnqualified(fixKwd(base->scoped()), scope);
4182 }
4183 else
4184 {
4185 C << getUnqualified("::Ice::Object", scope);
4186 }
4187 C << call;
4188 }
4189
AsyncCallbackVisitor(Output & h,Output &,const string & dllExport)4190 Slice::Gen::AsyncCallbackVisitor::AsyncCallbackVisitor(Output& h, Output&, const string& dllExport) :
4191 H(h), _dllExport(dllExport), _useWstring(false)
4192 {
4193 }
4194
4195 bool
visitModuleStart(const ModulePtr & p)4196 Slice::Gen::AsyncCallbackVisitor::visitModuleStart(const ModulePtr& p)
4197 {
4198 if(!p->hasNonLocalClassDefs() && !p->hasContentsWithMetaData("async-oneway"))
4199 {
4200 return false;
4201 }
4202
4203 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
4204
4205 H << sp << nl << "namespace " << fixKwd(p->name()) << nl << '{';
4206
4207 return true;
4208 }
4209
4210 void
visitModuleEnd(const ModulePtr &)4211 Slice::Gen::AsyncCallbackVisitor::visitModuleEnd(const ModulePtr&)
4212 {
4213 _useWstring = resetUseWstring(_useWstringHist);
4214
4215 H << sp << nl << '}';
4216 }
4217
4218 bool
visitClassDefStart(const ClassDefPtr & p)4219 Slice::Gen::AsyncCallbackVisitor::visitClassDefStart(const ClassDefPtr& p)
4220 {
4221 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
4222 return true;
4223 }
4224
4225 void
visitClassDefEnd(const ClassDefPtr &)4226 Slice::Gen::AsyncCallbackVisitor::visitClassDefEnd(const ClassDefPtr&)
4227 {
4228 _useWstring = resetUseWstring(_useWstringHist);
4229 }
4230
4231 void
visitOperation(const OperationPtr & p)4232 Slice::Gen::AsyncCallbackVisitor::visitOperation(const OperationPtr& p)
4233 {
4234 ClassDefPtr cl = ClassDefPtr::dynamicCast(p->container());
4235
4236 if(cl->isLocal() && !(cl->hasMetaData("async-oneway") || p->hasMetaData("async-oneway")))
4237 {
4238 return;
4239 }
4240
4241 //
4242 // Write the callback base class and callback smart pointer.
4243 //
4244 string delName = "Callback_" + cl->name() + "_" + p->name();
4245 H << sp;
4246 H << nl << "/**";
4247 H << nl << " * Base class for asynchronous callback wrapper classes used for calls to";
4248 H << nl << " * IceProxy" << fixKwd(cl->scoped()) << "::begin_" << p->name() << ".";
4249 H << nl << " * Create a wrapper instance by calling " << fixKwd(cl->scope()) << "new" << delName << ".";
4250 H << nl << " */";
4251 H << nl << "class " << delName << "_Base : public virtual ::IceInternal::CallbackBase { };";
4252 H << nl << "typedef ::IceUtil::Handle< " << delName << "_Base> " << delName << "Ptr;";
4253 }
4254
AsyncCallbackTemplateVisitor(Output & h,Output &,const string & dllExport)4255 Slice::Gen::AsyncCallbackTemplateVisitor::AsyncCallbackTemplateVisitor(Output& h, Output&, const string& dllExport)
4256 : H(h), _dllExport(dllExport), _useWstring(false)
4257 {
4258 }
4259
4260 bool
visitUnitStart(const UnitPtr & p)4261 Slice::Gen::AsyncCallbackTemplateVisitor::visitUnitStart(const UnitPtr& p)
4262 {
4263 return p->hasNonLocalClassDefs();
4264 }
4265
4266 void
visitUnitEnd(const UnitPtr &)4267 Slice::Gen::AsyncCallbackTemplateVisitor::visitUnitEnd(const UnitPtr&)
4268 {
4269 }
4270
4271 bool
visitModuleStart(const ModulePtr & p)4272 Slice::Gen::AsyncCallbackTemplateVisitor::visitModuleStart(const ModulePtr& p)
4273 {
4274 if(!p->hasNonLocalClassDefs())
4275 {
4276 return false;
4277 }
4278
4279 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
4280
4281 H << sp << nl << "namespace " << fixKwd(p->name()) << nl << '{';
4282 return true;
4283 }
4284
4285 void
visitModuleEnd(const ModulePtr &)4286 Slice::Gen::AsyncCallbackTemplateVisitor::visitModuleEnd(const ModulePtr&)
4287 {
4288 _useWstring = resetUseWstring(_useWstringHist);
4289 H << sp << nl << '}';
4290 }
4291
4292 bool
visitClassDefStart(const ClassDefPtr & p)4293 Slice::Gen::AsyncCallbackTemplateVisitor::visitClassDefStart(const ClassDefPtr& p)
4294 {
4295 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
4296 return true;
4297 }
4298
4299 void
visitClassDefEnd(const ClassDefPtr &)4300 Slice::Gen::AsyncCallbackTemplateVisitor::visitClassDefEnd(const ClassDefPtr&)
4301 {
4302 _useWstring = resetUseWstring(_useWstringHist);
4303 }
4304
4305 void
visitOperation(const OperationPtr & p)4306 Slice::Gen::AsyncCallbackTemplateVisitor::visitOperation(const OperationPtr& p)
4307 {
4308 generateOperation(p, false);
4309 generateOperation(p, true);
4310 }
4311
4312 void
generateOperation(const OperationPtr & p,bool withCookie)4313 Slice::Gen::AsyncCallbackTemplateVisitor::generateOperation(const OperationPtr& p, bool withCookie)
4314 {
4315 ClassDefPtr cl = ClassDefPtr::dynamicCast(p->container());
4316 if(cl->isLocal() || cl->operations().empty())
4317 {
4318 return;
4319 }
4320
4321 string clName = cl->name();
4322 string clScope = fixKwd(cl->scope());
4323 string delName = "Callback_" + clName + "_" + p->name();
4324 string delTmplName = (withCookie ? "Callback_" : "CallbackNC_") + clName + "_" + p->name();
4325
4326 TypePtr ret = p->returnType();
4327 string retS = inputTypeToString(ret, p->returnIsOptional(), clScope, p->getMetaData(), _useWstring);
4328 string retEndArg = getEndArg(ret, p->getMetaData(), "ret");
4329
4330 ParamDeclList outParams;
4331 vector<string> outArgs;
4332 vector<string> outDecls;
4333 vector<string> outDeclsEnd;
4334 vector<string> outEndArgs;
4335
4336 ParamDeclList paramList = p->parameters();
4337 for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
4338 {
4339 if((*q)->isOutParam())
4340 {
4341 outParams.push_back(*q);
4342 outArgs.push_back("iceP_" + (*q)->name());
4343 outEndArgs.push_back(getEndArg((*q)->type(), (*q)->getMetaData(), outArgs.back()));
4344 outDecls.push_back(
4345 inputTypeToString((*q)->type(), (*q)->optional(), clScope, (*q)->getMetaData(), _useWstring));
4346 }
4347 }
4348
4349 H << sp;
4350 string baseD;
4351 string inheritD;
4352 if(withCookie)
4353 {
4354 baseD = "::IceInternal::Callback<T, CT>";
4355 H << nl << "/**";
4356 H << nl << " * Type-safe asynchronous callback wrapper class with cookie support used for calls to";
4357 H << nl << " * IceProxy" << fixKwd(cl->scoped()) << "::begin_" << p->name() << ".";
4358 H << nl << " * Create a wrapper instance by calling " << fixKwd(cl->scope()) << "new" << delName << ".";
4359 H << nl << " */";
4360 H << nl << "template<class T, typename CT>";
4361 inheritD = p->returnsData() ? "::IceInternal::TwowayCallback<T, CT>" : "::IceInternal::OnewayCallback<T, CT>";
4362 }
4363 else
4364 {
4365 baseD = "::IceInternal::CallbackNC<T>";
4366 H << nl << "/**";
4367 H << nl << " * Type-safe asynchronous callback wrapper class used for calls to";
4368 H << nl << " * IceProxy" << fixKwd(cl->scoped()) << "::begin_" << p->name() << ".";
4369 H << nl << " * Create a wrapper instance by calling " << fixKwd(cl->scope()) << "new" << delName << ".";
4370 H << nl << " */";
4371 H << nl << "template<class T>";
4372 inheritD = p->returnsData() ? "::IceInternal::TwowayCallbackNC<T>" : "::IceInternal::OnewayCallbackNC<T>";
4373 }
4374
4375 H << nl << "class " << delTmplName << " : public " << delName << "_Base, public " << inheritD;
4376 H << sb;
4377 H.dec();
4378 H << nl << "public:";
4379 H.inc();
4380
4381 H << sp << nl << "typedef IceUtil::Handle<T> TPtr;";
4382
4383 string cookieT;
4384 string comCookieT;
4385 if(withCookie)
4386 {
4387 cookieT = "const CT&";
4388 comCookieT = " , const CT&";
4389 }
4390
4391 H << sp << nl << "typedef void (T::*Exception)(const ::Ice::Exception&" << comCookieT << ");";
4392 H << nl << "typedef void (T::*Sent)(bool" << comCookieT << ");";
4393 if(p->returnsData())
4394 {
4395 //
4396 // typedefs for callbacks.
4397 //
4398 H << nl << "typedef void (T::*Response)" << spar;
4399 if(ret)
4400 {
4401 H << retS;
4402 }
4403 H << outDecls;
4404 if(withCookie)
4405 {
4406 H << cookieT;
4407 }
4408 H << epar << ';';
4409 }
4410 else
4411 {
4412 H << nl << "typedef void (T::*Response)(" << cookieT << ");";
4413 }
4414
4415 //
4416 // constructor.
4417 //
4418 H << sp;
4419 H << nl << delTmplName << spar << "const TPtr& obj";
4420 H << "Response cb";
4421 H << "Exception excb";
4422 H << "Sent sentcb" << epar;
4423 H.inc();
4424 if(p->returnsData())
4425 {
4426 H << nl << ": " << inheritD + "(obj, cb != 0, excb, sentcb), _response(cb)";
4427 }
4428 else
4429 {
4430 H << nl << ": " << inheritD + "(obj, cb, excb, sentcb)";
4431 }
4432 H.dec();
4433 H << sb;
4434 H << eb;
4435
4436 if(p->returnsData())
4437 {
4438 //
4439 // completed.
4440 //
4441 H << sp;
4442 H << nl << "/// \\cond INTERNAL";
4443 H << nl << "virtual void completed(const " << getUnqualified("::Ice::AsyncResultPtr&", clScope)
4444 << " result) const";
4445 H << sb;
4446 H << nl << clName << "Prx proxy = " << clName << "Prx::uncheckedCast(result->getProxy());";
4447 writeAllocateCode(H, outParams, p, true, clScope,
4448 _useWstring | TypeContextInParam | TypeContextAMICallPrivateEnd);
4449 H << nl << "try";
4450 H << sb;
4451 H << nl;
4452 if(!usePrivateEnd(p))
4453 {
4454 if(ret)
4455 {
4456 H << retEndArg << " = ";
4457 }
4458 H << "proxy->end_" << p->name() << spar << outEndArgs << "result" << epar << ';';
4459 }
4460 else
4461 {
4462 H << "proxy->_iceI_end_" << p->name() << spar << outEndArgs;
4463 if(ret)
4464 {
4465 H << retEndArg;
4466 }
4467 H << "result" << epar << ';';
4468 }
4469 writeEndCode(H, outParams, p, true);
4470 H << eb;
4471 H << nl << "catch(const ::Ice::Exception& ex)";
4472 H << sb;
4473
4474 H << nl << "" << baseD << "::exception(result, ex);";
4475 H << nl << "return;";
4476 H << eb;
4477 H << nl << "if(_response)";
4478 H << sb;
4479 H << nl << "(" << baseD << "::_callback.get()->*_response)" << spar;
4480 if(ret)
4481 {
4482 H << "ret";
4483 }
4484 H << outArgs;
4485 if(withCookie)
4486 {
4487 H << "CT::dynamicCast(result->getCookie())";
4488 }
4489 H << epar << ';';
4490 H << eb;
4491 H << eb;
4492 H << nl << "/// \\endcond";
4493 H.dec();
4494 H << sp << nl << "private:";
4495 H.inc();
4496 H << sp << nl << "Response _response;";
4497 }
4498 H << eb << ';';
4499
4500 // Factory method
4501 for(int i = 0; i < 2; i++)
4502 {
4503 string callbackT = i == 0 ? "const IceUtil::Handle<T>&" : "T*";
4504
4505 H << sp;
4506 H << nl << "/**";
4507 H << nl << " * Creates a callback wrapper instance that delegates to your object.";
4508 if(withCookie)
4509 {
4510 H << nl << " * Use this overload when your callback methods receive a cookie value.";
4511 }
4512 H << nl << " * @param instance The callback object.";
4513 H << nl << " * @param cb The success method of the callback object.";
4514 H << nl << " * @param excb The exception method of the callback object.";
4515 H << nl << " * @param sentcb The sent method of the callback object.";
4516 H << nl << " * @return An object that can be passed to an asynchronous invocation of IceProxy"
4517 << clScope << clName << "::begin_" << p->name() << ".";
4518 H << nl << " */";
4519 if(withCookie)
4520 {
4521 cookieT = "const CT&";
4522 comCookieT = ", const CT&";
4523 H << nl << "template<class T, typename CT> " << delName << "Ptr";
4524 }
4525 else
4526 {
4527 H << nl << "template<class T> " << delName << "Ptr";
4528 }
4529
4530 H << nl << "new" << delName << "(" << callbackT << " instance, ";
4531 if(p->returnsData())
4532 {
4533 H << "void (T::*cb)" << spar;
4534 if(ret)
4535 {
4536 H << retS;
4537 }
4538 H << outDecls;
4539 if(withCookie)
4540 {
4541 H << cookieT;
4542 }
4543 H << epar << ", ";
4544 }
4545 else
4546 {
4547 H << "void (T::*cb)(" << cookieT << "), ";
4548 }
4549 H << "void (T::*excb)(" << "const ::Ice::Exception&" << comCookieT << "), ";
4550 H << "void (T::*sentcb)(bool" << comCookieT << ") = 0)";
4551 H << sb;
4552 if(withCookie)
4553 {
4554 H << nl << "return new " << delTmplName << "<T, CT>(instance, cb, excb, sentcb);";
4555 }
4556 else
4557 {
4558 H << nl << "return new " << delTmplName << "<T>(instance, cb, excb, sentcb);";
4559 }
4560 H << eb;
4561
4562 if(!ret && outParams.empty())
4563 {
4564 H << sp;
4565 H << nl << "/**";
4566 H << nl << " * Creates a callback wrapper instance that delegates to your object.";
4567 if(withCookie)
4568 {
4569 H << nl << " * Use this overload when your callback methods receive a cookie value.";
4570 }
4571 H << nl << " * @param instance The callback object.";
4572 H << nl << " * @param excb The exception method of the callback object.";
4573 H << nl << " * @param sentcb The sent method of the callback object.";
4574 H << nl << " * @return An object that can be passed to an asynchronous invocation of IceProxy"
4575 << clScope << clName << "::begin_" << p->name() << ".";
4576 H << nl << " */";
4577 if(withCookie)
4578 {
4579 H << nl << "template<class T, typename CT> " << delName << "Ptr";
4580 }
4581 else
4582 {
4583 H << nl << "template<class T> " << delName << "Ptr";
4584 }
4585 H << nl << "new" << delName << "(" << callbackT << " instance, ";
4586 H << "void (T::*excb)(" << "const ::Ice::Exception&" << comCookieT << "), ";
4587 H << "void (T::*sentcb)(bool" << comCookieT << ") = 0)";
4588 H << sb;
4589 if(withCookie)
4590 {
4591 H << nl << "return new " << delTmplName << "<T, CT>(instance, 0, excb, sentcb);";
4592 }
4593 else
4594 {
4595 H << nl << "return new " << delTmplName << "<T>(instance, 0, excb, sentcb);";
4596 }
4597 H << eb;
4598 }
4599 }
4600 }
4601
ImplVisitor(Output & h,Output & c,const string & dllExport)4602 Slice::Gen::ImplVisitor::ImplVisitor(Output& h, Output& c, const string& dllExport) :
4603 H(h), C(c), _dllExport(dllExport), _useWstring(false)
4604 {
4605 }
4606
4607 string
defaultValue(const TypePtr & type,const string & scope,const StringList & metaData) const4608 Slice::Gen::ImplVisitor::defaultValue(const TypePtr& type, const string& scope, const StringList& metaData) const
4609 {
4610 BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
4611 if(builtin)
4612 {
4613 switch(builtin->kind())
4614 {
4615 case Builtin::KindBool:
4616 {
4617 return "false";
4618 }
4619 case Builtin::KindByte:
4620 case Builtin::KindShort:
4621 case Builtin::KindInt:
4622 case Builtin::KindLong:
4623 {
4624 return "0";
4625 }
4626 case Builtin::KindFloat:
4627 case Builtin::KindDouble:
4628 {
4629 return "0.0";
4630 }
4631 case Builtin::KindString:
4632 {
4633 return "::std::string()";
4634 }
4635 case Builtin::KindValue:
4636 case Builtin::KindObject:
4637 case Builtin::KindObjectProxy:
4638 case Builtin::KindLocalObject:
4639 {
4640 return "0";
4641 }
4642 }
4643 }
4644 else
4645 {
4646 ProxyPtr prx = ProxyPtr::dynamicCast(type);
4647
4648 if(ProxyPtr::dynamicCast(type) || ClassDeclPtr::dynamicCast(type))
4649 {
4650 return "0";
4651 }
4652
4653 StructPtr st = StructPtr::dynamicCast(type);
4654 if(st)
4655 {
4656 return getUnqualified(fixKwd(st->scoped()), scope) + "()";
4657 }
4658
4659 EnumPtr en = EnumPtr::dynamicCast(type);
4660 if(en)
4661 {
4662 EnumeratorList enumerators = en->enumerators();
4663 return getUnqualified(fixKwd(en->scope() + enumerators.front()->name()), scope);
4664 }
4665
4666 SequencePtr seq = SequencePtr::dynamicCast(type);
4667 if(seq)
4668 {
4669 return typeToString(seq, scope, metaData, _useWstring | TypeContextCpp11) + "()";
4670 }
4671
4672 DictionaryPtr dict = DictionaryPtr::dynamicCast(type);
4673 if(dict)
4674 {
4675 return getUnqualified(fixKwd(dict->scoped()), scope) + "()";
4676 }
4677 }
4678
4679 assert(false);
4680 return "???";
4681 }
4682
4683 bool
visitModuleStart(const ModulePtr & p)4684 Slice::Gen::ImplVisitor::visitModuleStart(const ModulePtr& p)
4685 {
4686 if(!p->hasClassDefs())
4687 {
4688 return false;
4689 }
4690 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
4691 H << sp << nl << "namespace " << fixKwd(p->name()) << nl << '{';
4692 return true;
4693 }
4694
4695 void
visitModuleEnd(const ModulePtr &)4696 Slice::Gen::ImplVisitor::visitModuleEnd(const ModulePtr&)
4697 {
4698 H << sp;
4699 H << nl << '}';
4700
4701 _useWstring = resetUseWstring(_useWstringHist);
4702 }
4703
4704 bool
visitClassDefStart(const ClassDefPtr & p)4705 Slice::Gen::ImplVisitor::visitClassDefStart(const ClassDefPtr& p)
4706 {
4707 if(!p->isAbstract())
4708 {
4709 return false;
4710 }
4711
4712 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
4713
4714 string name = p->name();
4715 string scope = fixKwd(p->scope());
4716 string cls = scope.substr(2) + name + "I";
4717 ClassList bases = p->bases();
4718
4719 H << sp;
4720 H << nl << "class " << name << "I : public virtual " << fixKwd(name);
4721
4722 H << sb;
4723 H.dec();
4724 H << nl << "public:";
4725 H.inc();
4726
4727 OperationList ops = p->allOperations();
4728
4729 for(OperationList::const_iterator r = ops.begin(); r != ops.end(); ++r)
4730 {
4731 OperationPtr op = (*r);
4732 string opName = op->name();
4733 string isConst = ((op->mode() == Operation::Nonmutating) || op->hasMetaData("cpp:const")) ? " const" : "";
4734
4735 string classScopedAMD = "AMD_" + ClassDefPtr::dynamicCast(op->container())->name();
4736
4737 TypePtr ret = op->returnType();
4738 string retS = returnTypeToString(ret, op->returnIsOptional(), "", op->getMetaData(), _useWstring);
4739
4740 if(!p->isLocal() && (p->hasMetaData("amd") || op->hasMetaData("amd")))
4741 {
4742 H << sp << nl << "virtual void " << opName << "_async(";
4743 H.useCurrentPosAsIndent();
4744 H << "const " << classScopedAMD << '_' << opName << "Ptr&";
4745 ParamDeclList paramList = op->parameters();
4746
4747 for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
4748 {
4749 if(!(*q)->isOutParam())
4750 {
4751 H << ',' << nl << inputTypeToString((*q)->type(), (*q)->optional(), scope, (*q)->getMetaData(),
4752 _useWstring);
4753 }
4754 }
4755 H << ',' << nl << "const Ice::Current&";
4756 H.restoreIndent();
4757 H << ")" << isConst << ';';
4758
4759 C << sp << nl << "void" << nl << scope << name << "I::" << opName << "_async(";
4760 C.useCurrentPosAsIndent();
4761 C << "const " << classScopedAMD << '_' << opName << "Ptr& " << opName << "CB";
4762 for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
4763 {
4764 if(!(*q)->isOutParam())
4765 {
4766 C << ',' << nl << inputTypeToString((*q)->type(), (*q)->optional(), scope, (*q)->getMetaData(),
4767 _useWstring) << ' ' << fixKwd((*q)->name());
4768 }
4769 }
4770 C << ',' << nl << "const Ice::Current& current";
4771 C.restoreIndent();
4772 C << ")" << isConst;
4773 C << sb;
4774
4775 string result = "r";
4776 for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
4777 {
4778 if((*q)->name() == result)
4779 {
4780 result = "_" + result;
4781 break;
4782 }
4783 }
4784
4785 C << nl << opName << "CB->ice_response(";
4786 if(ret)
4787 {
4788 C << defaultValue(ret, scope, op->getMetaData());
4789 }
4790 for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
4791 {
4792 if((*q)->isOutParam())
4793 {
4794 if(ret || q != paramList.begin())
4795 {
4796 C << ", ";
4797 }
4798 C << defaultValue((*q)->type(), scope, op->getMetaData());
4799 }
4800 }
4801 C << ");";
4802
4803 C << eb;
4804 }
4805 else
4806 {
4807 H << sp << nl << "virtual " << getUnqualified(retS, scope) << ' ' << fixKwd(opName) << '(';
4808 H.useCurrentPosAsIndent();
4809 ParamDeclList paramList = op->parameters();
4810 for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
4811 {
4812 if(q != paramList.begin())
4813 {
4814 H << ',' << nl;
4815 }
4816 if((*q)->isOutParam())
4817 {
4818 H << outputTypeToString((*q)->type(), (*q)->optional(), scope, (*q)->getMetaData(), _useWstring);
4819 }
4820 else
4821 {
4822 H << inputTypeToString((*q)->type(), (*q)->optional(), scope, (*q)->getMetaData(), _useWstring);
4823 }
4824 }
4825 if(!p->isLocal())
4826 {
4827 if(!paramList.empty())
4828 {
4829 H << ',' << nl;
4830 }
4831 H << "const Ice::Current&";
4832 }
4833 H.restoreIndent();
4834
4835 H << ")" << isConst << ';';
4836
4837 C << sp << nl << retS << nl;
4838 C << scope.substr(2) << name << "I::" << fixKwd(opName) << '(';
4839 C.useCurrentPosAsIndent();
4840 for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
4841 {
4842 if(q != paramList.begin())
4843 {
4844 C << ',' << nl;
4845 }
4846 if((*q)->isOutParam())
4847 {
4848 C << outputTypeToString((*q)->type(), (*q)->optional(), scope, (*q)->getMetaData(), _useWstring) << " "
4849 << fixKwd((*q)->name());
4850 }
4851 else
4852 {
4853 C << inputTypeToString((*q)->type(), (*q)->optional(), scope, (*q)->getMetaData(), _useWstring) << " /*"
4854 << fixKwd((*q)->name()) << "*/";
4855 }
4856 }
4857 if(!p->isLocal())
4858 {
4859 if(!paramList.empty())
4860 {
4861 C << ',' << nl;
4862 }
4863 C << "const Ice::Current& current";
4864 }
4865 C.restoreIndent();
4866 C << ')';
4867 C << isConst;
4868 C << sb;
4869
4870 if(ret)
4871 {
4872 C << nl << "return " << defaultValue(ret, scope, op->getMetaData()) << ";";
4873 }
4874
4875 C << eb;
4876 }
4877 }
4878
4879 H << eb << ';';
4880
4881 _useWstring = resetUseWstring(_useWstringHist);
4882
4883 return true;
4884 }
4885
AsyncVisitor(Output & h,Output & c,const string & dllExport)4886 Slice::Gen::AsyncVisitor::AsyncVisitor(Output& h, Output& c, const string& dllExport) :
4887 H(h), C(c), _dllExport(dllExport), _useWstring(false)
4888 {
4889 }
4890
4891 bool
visitModuleStart(const ModulePtr & p)4892 Slice::Gen::AsyncVisitor::visitModuleStart(const ModulePtr& p)
4893 {
4894 if(!p->hasNonLocalClassDecls() || !p->hasContentsWithMetaData("amd"))
4895 {
4896 return false;
4897 }
4898
4899 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
4900
4901 string name = fixKwd(p->name());
4902
4903 H << sp << nl << "namespace " << name << nl << '{';
4904
4905 return true;
4906 }
4907
4908 void
visitModuleEnd(const ModulePtr &)4909 Slice::Gen::AsyncVisitor::visitModuleEnd(const ModulePtr&)
4910 {
4911 H << sp << nl << '}';
4912
4913 _useWstring = resetUseWstring(_useWstringHist);
4914 }
4915
4916 bool
visitClassDefStart(const ClassDefPtr & p)4917 Slice::Gen::AsyncVisitor::visitClassDefStart(const ClassDefPtr& p)
4918 {
4919 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
4920 return true;
4921 }
4922
4923 void
visitClassDefEnd(const ClassDefPtr &)4924 Slice::Gen::AsyncVisitor::visitClassDefEnd(const ClassDefPtr&)
4925 {
4926 _useWstring = resetUseWstring(_useWstringHist);
4927 }
4928
4929 void
visitOperation(const OperationPtr & p)4930 Slice::Gen::AsyncVisitor::visitOperation(const OperationPtr& p)
4931 {
4932 ContainerPtr container = p->container();
4933 ClassDefPtr cl = ClassDefPtr::dynamicCast(container);
4934
4935 if(cl->isLocal() || (!cl->hasMetaData("amd") && !p->hasMetaData("amd")))
4936 {
4937 return;
4938 }
4939
4940 string name = p->name();
4941
4942 string className = cl->name();
4943 string classNameAMD = "AMD_" + className;
4944 string classScope = fixKwd(cl->scope());
4945 string classScopedAMD = classScope + classNameAMD;
4946
4947 TypePtr ret = p->returnType();
4948 string retS = inputTypeToString(ret, p->returnIsOptional(), classScope, p->getMetaData(), _useWstring);
4949
4950 string resultParam = "result";
4951 ParamDeclList paramList = p->outParameters();
4952 for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
4953 {
4954 if((*q)->name() == "result")
4955 {
4956 resultParam = "result_";
4957 break;
4958 }
4959 }
4960
4961 vector<string> paramsAMD;
4962
4963 if(ret)
4964 {
4965 paramsAMD.push_back(inputTypeToString(ret, p->returnIsOptional(), classScope, p->getMetaData(), _useWstring) +
4966 " " + resultParam);
4967 }
4968
4969 for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
4970 {
4971 string paramName = fixKwd((*q)->name());
4972 TypePtr type = (*q)->type();
4973 string typeString = inputTypeToString(type, (*q)->optional(), classScope, (*q)->getMetaData(), _useWstring);
4974 paramsAMD.push_back(typeString + " " + paramName);
4975 }
4976
4977 string cbName = classNameAMD + '_' + name;
4978
4979 CommentPtr comment = p->parseComment(false);
4980
4981 H << sp;
4982 H << nl << "/**";
4983 H << nl << " * AMD callback class for " << fixKwd(p->scoped()).substr(2) << "_async.";
4984 H << nl << " * Call the ice_response method for a successful completion, or the ice_exception";
4985 H << nl << " * method in the case of an error.";
4986 H << nl << " */";
4987 H << nl << "class " << _dllExport << cbName << " : public virtual "
4988 << getUnqualified("::Ice::AMDCallback", classScope);
4989 H << sb;
4990 H.dec();
4991 H << nl << "public:";
4992 H.inc();
4993
4994 // Out of line dtor to avoid weak vtable
4995 H << sp << nl << "virtual ~" << cbName << "();";
4996 C << sp;
4997 C << nl << classScope.substr(2) << cbName << "::~" << cbName << "()";
4998 C << sb;
4999 C << eb;
5000
5001 H << sp;
5002 H << nl << "/**";
5003 H << nl << " * Call ice_response for a successful completion.";
5004 if(comment)
5005 {
5006 StringList preParams;
5007 StringList returns = comment->returns();
5008 if(ret && !returns.empty())
5009 {
5010 preParams = returns;
5011 preParams.pop_front();
5012 preParams.push_front("@param " + resultParam + " " + returns.front());
5013 }
5014 writeOpDocParams(H, p, comment, OpDocOutParams, preParams);
5015 }
5016 H << nl << " */";
5017 H << nl << "virtual void ice_response" << spar << paramsAMD << epar << " = 0;";
5018 H << eb << ';';
5019 H << sp << nl << "typedef ::IceUtil::Handle< " << classScopedAMD << '_' << name << "> "
5020 << classNameAMD << '_' << name << "Ptr;";
5021 }
5022
AsyncImplVisitor(Output & h,Output & c,const string & dllExport)5023 Slice::Gen::AsyncImplVisitor::AsyncImplVisitor(Output& h, Output& c, const string& dllExport) :
5024 H(h), C(c), _dllExport(dllExport), _useWstring(false)
5025 {
5026 }
5027
5028 bool
visitUnitStart(const UnitPtr & p)5029 Slice::Gen::AsyncImplVisitor::visitUnitStart(const UnitPtr& p)
5030 {
5031 if(!p->hasNonLocalClassDecls() || !p->hasContentsWithMetaData("amd"))
5032 {
5033 return false;
5034 }
5035
5036 H << sp;
5037 H << nl << "/// \\cond INTERNAL";
5038 H << nl << "namespace IceAsync" << nl << '{';
5039
5040 return true;
5041 }
5042
5043 void
visitUnitEnd(const UnitPtr &)5044 Slice::Gen::AsyncImplVisitor::visitUnitEnd(const UnitPtr&)
5045 {
5046 H << sp << nl << '}';
5047 H << nl << "/// \\endcond";
5048 }
5049
5050 bool
visitModuleStart(const ModulePtr & p)5051 Slice::Gen::AsyncImplVisitor::visitModuleStart(const ModulePtr& p)
5052 {
5053 if(!p->hasNonLocalClassDecls() || !p->hasContentsWithMetaData("amd"))
5054 {
5055 return false;
5056 }
5057
5058 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
5059
5060 string name = fixKwd(p->name());
5061
5062 H << sp << nl << "namespace " << name << nl << '{';
5063
5064 return true;
5065 }
5066
5067 void
visitModuleEnd(const ModulePtr &)5068 Slice::Gen::AsyncImplVisitor::visitModuleEnd(const ModulePtr&)
5069 {
5070 H << sp << nl << '}';
5071
5072 _useWstring = resetUseWstring(_useWstringHist);
5073 }
5074
5075 bool
visitClassDefStart(const ClassDefPtr & p)5076 Slice::Gen::AsyncImplVisitor::visitClassDefStart(const ClassDefPtr& p)
5077 {
5078 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
5079 return true;
5080 }
5081
5082 void
visitClassDefEnd(const ClassDefPtr &)5083 Slice::Gen::AsyncImplVisitor::visitClassDefEnd(const ClassDefPtr&)
5084 {
5085 _useWstring = resetUseWstring(_useWstringHist);
5086 }
5087
5088 void
visitOperation(const OperationPtr & p)5089 Slice::Gen::AsyncImplVisitor::visitOperation(const OperationPtr& p)
5090 {
5091 ContainerPtr container = p->container();
5092 ClassDefPtr cl = ClassDefPtr::dynamicCast(container);
5093
5094 if(cl->isLocal() || (!cl->hasMetaData("amd") && !p->hasMetaData("amd")))
5095 {
5096 return;
5097 }
5098
5099 string name = p->name();
5100
5101 string classNameAMD = "AMD_" + cl->name();
5102 string classScope = fixKwd(cl->scope());
5103 string classScopedAMD = classScope + classNameAMD;
5104
5105 string params;
5106 string paramsDecl;
5107 string args;
5108
5109 TypePtr ret = p->returnType();
5110 string retS = inputTypeToString(ret, p->returnIsOptional(), "", p->getMetaData(), _useWstring);
5111
5112 if(ret)
5113 {
5114 params += retS;
5115 paramsDecl += retS;
5116 paramsDecl += ' ';
5117 paramsDecl += "ret";
5118 args += "ret";
5119 }
5120
5121 ParamDeclList outParams;
5122 ParamDeclList paramList = p->parameters();
5123 for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
5124 {
5125 if((*q)->isOutParam())
5126 {
5127 string paramName = fixKwd((*q)->name());
5128 TypePtr type = (*q)->type();
5129 string typeString = inputTypeToString(type, (*q)->optional(), "", (*q)->getMetaData(), _useWstring);
5130
5131 if(ret || !outParams.empty())
5132 {
5133 params += ", ";
5134 paramsDecl += ", ";
5135 args += ", ";
5136 }
5137
5138 params += typeString;
5139 paramsDecl += typeString;
5140 paramsDecl += ' ';
5141 paramsDecl += paramName;
5142 args += paramName;
5143
5144 outParams.push_back(*q);
5145 }
5146 }
5147
5148 H.zeroIndent();
5149 H << sp;
5150 H << nl << "#if defined(_MSC_VER) && (_MSC_VER >= 1900)";
5151 H << nl << "# pragma warning(push)";
5152 H << nl << "# pragma warning(disable:4239)";
5153 H << nl << "#endif";
5154 H.restoreIndent();
5155
5156 H << sp << nl << "class " << _dllExport << classNameAMD << '_' << name
5157 << " : public " << classScopedAMD << '_' << name << ", public ::IceInternal::IncomingAsync";
5158 H << sb;
5159 H.dec();
5160 H << nl << "public:";
5161 H.inc();
5162
5163 H << sp;
5164 H << nl << classNameAMD << '_' << name << "(::IceInternal::Incoming&);";
5165
5166 H << sp;
5167 H << nl << "virtual void ice_response(" << params << ");";
5168 H << eb << ';';
5169
5170 H.zeroIndent();
5171 H << sp;
5172 H << nl << "#if defined(_MSC_VER) && (_MSC_VER >= 1900)";
5173 H << nl << "# pragma warning(pop)";
5174 H << nl << "#endif";
5175 H.restoreIndent();
5176
5177 C << sp;
5178 C << nl << "/// \\cond INTERNAL";
5179 C << nl << "IceAsync" << classScopedAMD << '_' << name << "::" << classNameAMD << '_' << name
5180 << "(::IceInternal::Incoming& in) :";
5181 C.inc();
5182 C << nl << "::IceInternal::IncomingAsync(in)";
5183 C.dec();
5184 C << sb;
5185 C << eb;
5186
5187 C << sp << nl << "void";
5188 C << nl << "IceAsync" << classScopedAMD << '_' << name << "::ice_response(" << paramsDecl << ')';
5189 C << sb;
5190 if(ret || !outParams.empty())
5191 {
5192 C << nl << "::Ice::OutputStream* ostr = startWriteParams();";
5193 writeMarshalCode(C, outParams, p, false, TypeContextInParam);
5194 if(p->returnsClasses(false))
5195 {
5196 C << nl << "ostr->writePendingValues();";
5197 }
5198 C << nl << "endWriteParams();";
5199 }
5200 else
5201 {
5202 C << nl << "writeEmptyParams();";
5203 }
5204 C << nl << "completed();";
5205 C << eb;
5206 C << nl << "/// \\endcond";
5207 }
5208
StreamVisitor(Output & h,Output & c,const string & dllExport)5209 Slice::Gen::StreamVisitor::StreamVisitor(Output& h, Output& c, const string& dllExport) :
5210 H(h),
5211 C(c),
5212 _dllExport(dllExport)
5213 {
5214 }
5215
5216 bool
visitModuleStart(const ModulePtr & m)5217 Slice::Gen::StreamVisitor::visitModuleStart(const ModulePtr& m)
5218 {
5219 if(!m->hasNonLocalContained(Contained::ContainedTypeStruct) &&
5220 !m->hasNonLocalContained(Contained::ContainedTypeEnum) &&
5221 !m->hasNonLocalContained(Contained::ContainedTypeClass) &&
5222 !m->hasNonLocalContained(Contained::ContainedTypeException))
5223 {
5224 return false;
5225 }
5226
5227 if(UnitPtr::dynamicCast(m->container()))
5228 {
5229 //
5230 // Only emit this for the top-level module.
5231 //
5232 H << sp;
5233 H << nl << "/// \\cond STREAM";
5234 H << nl << "namespace Ice" << nl << '{' << sp;
5235
5236 C << sp;
5237 C << nl << "namespace Ice" << nl << '{';
5238 }
5239
5240 return true;
5241 }
5242
5243 void
visitModuleEnd(const ModulePtr & m)5244 Slice::Gen::StreamVisitor::visitModuleEnd(const ModulePtr& m)
5245 {
5246 if(UnitPtr::dynamicCast(m->container()))
5247 {
5248 //
5249 // Only emit this for the top-level module.
5250 //
5251 H << nl << '}';
5252 H << nl << "/// \\endcond";
5253 C << nl << '}';
5254 }
5255 }
5256
5257 bool
visitClassDefStart(const ClassDefPtr & c)5258 Slice::Gen::StreamVisitor::visitClassDefStart(const ClassDefPtr& c)
5259 {
5260 if(!c->isLocal())
5261 {
5262 writeStreamHelpers(H, c, c->dataMembers(), c->hasBaseDataMembers(), true, false);
5263 }
5264 return false;
5265 }
5266
5267 bool
visitExceptionStart(const ExceptionPtr & p)5268 Slice::Gen::StreamVisitor::visitExceptionStart(const ExceptionPtr& p)
5269 {
5270 if(!p->isLocal())
5271 {
5272 string scoped = p->scoped();
5273 H << nl << "template<>";
5274 H << nl << "struct StreamableTraits< " << fixKwd(scoped) << ">";
5275 H << sb;
5276 H << nl << "static const StreamHelperCategory helper = StreamHelperCategoryUserException;";
5277 H << eb << ";" << nl;
5278
5279 writeStreamHelpers(H, p, p->dataMembers(), p->hasBaseDataMembers(), true, false);
5280 }
5281 return false;
5282 }
5283
5284 bool
visitStructStart(const StructPtr & p)5285 Slice::Gen::StreamVisitor::visitStructStart(const StructPtr& p)
5286 {
5287 if(!p->isLocal())
5288 {
5289 bool classMetaData = findMetaData(p->getMetaData(), false) == "%class";
5290 string scoped = p->scoped();
5291
5292 string fullStructName = classMetaData ? fixKwd(scoped + "Ptr") : fixKwd(scoped);
5293
5294 H << nl << "template<>";
5295
5296 H << nl << "struct StreamableTraits< " << fullStructName << ">";
5297
5298 H << sb;
5299 if(classMetaData)
5300 {
5301 H << nl << "static const StreamHelperCategory helper = StreamHelperCategoryStructClass;";
5302 }
5303 else
5304 {
5305 H << nl << "static const StreamHelperCategory helper = StreamHelperCategoryStruct;";
5306 }
5307 H << nl << "static const int minWireSize = " << p->minWireSize() << ";";
5308 if(p->isVariableLength())
5309 {
5310 H << nl << "static const bool fixedLength = false;";
5311 }
5312 else
5313 {
5314 H << nl << "static const bool fixedLength = true;";
5315 }
5316 H << eb << ";" << nl;
5317
5318 writeStreamHelpers(H, p, p->dataMembers(), false, true, false);
5319 }
5320 return false;
5321 }
5322
5323 void
visitEnum(const EnumPtr & p)5324 Slice::Gen::StreamVisitor::visitEnum(const EnumPtr& p)
5325 {
5326 if(!p->isLocal())
5327 {
5328 string scoped = fixKwd(p->scoped());
5329 H << nl << "template<>";
5330 H << nl << "struct StreamableTraits< " << scoped << ">";
5331 H << sb;
5332 H << nl << "static const StreamHelperCategory helper = StreamHelperCategoryEnum;";
5333 H << nl << "static const int minValue = " << p->minValue() << ";";
5334 H << nl << "static const int maxValue = " << p->maxValue() << ";";
5335 H << nl << "static const int minWireSize = " << p->minWireSize() << ";";
5336 H << nl << "static const bool fixedLength = false;";
5337 H << eb << ";" << nl;
5338 }
5339 }
5340
5341 void
validateMetaData(const UnitPtr & u)5342 Slice::Gen::validateMetaData(const UnitPtr& u)
5343 {
5344 MetaDataVisitor visitor;
5345 u->visit(&visitor, false);
5346 }
5347
5348 bool
visitUnitStart(const UnitPtr & p)5349 Slice::Gen::MetaDataVisitor::visitUnitStart(const UnitPtr& p)
5350 {
5351 static const string prefix = "cpp:";
5352
5353 //
5354 // Validate global metadata in the top-level file and all included files.
5355 // Note that these metadata can only be cpp:, never cpp98: or cpp11:
5356 //
5357 StringList files = p->allFiles();
5358
5359 for(StringList::iterator q = files.begin(); q != files.end(); ++q)
5360 {
5361 string file = *q;
5362 DefinitionContextPtr dc = p->findDefinitionContext(file);
5363 assert(dc);
5364 StringList globalMetaData = dc->getMetaData();
5365 int headerExtension = 0;
5366 int sourceExtension = 0;
5367 int dllExport = 0;
5368 for(StringList::const_iterator r = globalMetaData.begin(); r != globalMetaData.end();)
5369 {
5370 string s = *r++;
5371 if(s.find(prefix) == 0)
5372 {
5373 static const string cppIncludePrefix = "cpp:include:";
5374 static const string cppHeaderExtPrefix = "cpp:header-ext:";
5375 static const string cppSourceExtPrefix = "cpp:source-ext:";
5376 static const string cppDllExportPrefix = "cpp:dll-export:";
5377 static const string cppDoxygenIncludePrefix = "cpp:doxygen:include:";
5378
5379 if(s.find(cppIncludePrefix) == 0 && s.size() > cppIncludePrefix.size())
5380 {
5381 continue;
5382 }
5383 else if(s.find(cppHeaderExtPrefix) == 0 && s.size() > cppHeaderExtPrefix.size())
5384 {
5385 headerExtension++;
5386 if(headerExtension > 1)
5387 {
5388 ostringstream ostr;
5389 ostr << "ignoring invalid global metadata `" << s
5390 << "': directive can appear only once per file";
5391 dc->warning(InvalidMetaData, file, -1, ostr.str());
5392 globalMetaData.remove(s);
5393 }
5394 continue;
5395 }
5396 else if(s.find(cppSourceExtPrefix) == 0 && s.size() > cppSourceExtPrefix.size())
5397 {
5398 sourceExtension++;
5399 if(sourceExtension > 1)
5400 {
5401 ostringstream ostr;
5402 ostr << "ignoring invalid global metadata `" << s
5403 << "': directive can appear only once per file";
5404 dc->warning(InvalidMetaData, file, -1, ostr.str());
5405 globalMetaData.remove(s);
5406 }
5407 continue;
5408 }
5409 else if(s.find(cppDllExportPrefix) == 0 && s.size() > cppDllExportPrefix.size())
5410 {
5411 dllExport++;
5412 if(dllExport > 1)
5413 {
5414 ostringstream ostr;
5415 ostr << "ignoring invalid global metadata `" << s
5416 << "': directive can appear only once per file";
5417 dc->warning(InvalidMetaData, file, -1, ostr.str());
5418
5419 globalMetaData.remove(s);
5420 }
5421 continue;
5422 }
5423 else if(s.find(cppDoxygenIncludePrefix) == 0 && s.size() > cppDoxygenIncludePrefix.size())
5424 {
5425 continue;
5426 }
5427
5428 ostringstream ostr;
5429 ostr << "ignoring invalid global metadata `" << s << "'";
5430 dc->warning(InvalidMetaData, file, -1, ostr.str());
5431 globalMetaData.remove(s);
5432 }
5433
5434 }
5435 dc->setMetaData(globalMetaData);
5436 }
5437
5438 return true;
5439 }
5440
5441 bool
visitModuleStart(const ModulePtr & p)5442 Slice::Gen::MetaDataVisitor::visitModuleStart(const ModulePtr& p)
5443 {
5444 StringList metaData = validate(p, p->getMetaData(), p->file(), p->line());
5445 p->setMetaData(metaData);
5446 return true;
5447 }
5448
5449 void
visitModuleEnd(const ModulePtr &)5450 Slice::Gen::MetaDataVisitor::visitModuleEnd(const ModulePtr&)
5451 {
5452 }
5453
5454 void
visitClassDecl(const ClassDeclPtr & p)5455 Slice::Gen::MetaDataVisitor::visitClassDecl(const ClassDeclPtr& p)
5456 {
5457 StringList metaData = validate(p, p->getMetaData(), p->file(), p->line());
5458 p->setMetaData(metaData);
5459 }
5460
5461 bool
visitClassDefStart(const ClassDefPtr & p)5462 Slice::Gen::MetaDataVisitor::visitClassDefStart(const ClassDefPtr& p)
5463 {
5464 StringList metaData = validate(p, p->getMetaData(), p->file(), p->line());
5465 p->setMetaData(metaData);
5466 return true;
5467 }
5468
5469 void
visitClassDefEnd(const ClassDefPtr &)5470 Slice::Gen::MetaDataVisitor::visitClassDefEnd(const ClassDefPtr&)
5471 {
5472 }
5473
5474 bool
visitExceptionStart(const ExceptionPtr & p)5475 Slice::Gen::MetaDataVisitor::visitExceptionStart(const ExceptionPtr& p)
5476 {
5477 StringList metaData = validate(p, p->getMetaData(), p->file(), p->line());
5478 p->setMetaData(metaData);
5479 return true;
5480 }
5481
5482 void
visitExceptionEnd(const ExceptionPtr &)5483 Slice::Gen::MetaDataVisitor::visitExceptionEnd(const ExceptionPtr&)
5484 {
5485 }
5486
5487 bool
visitStructStart(const StructPtr & p)5488 Slice::Gen::MetaDataVisitor::visitStructStart(const StructPtr& p)
5489 {
5490 StringList metaData = validate(p, p->getMetaData(), p->file(), p->line());
5491 p->setMetaData(metaData);
5492 return true;
5493 }
5494
5495 void
visitStructEnd(const StructPtr &)5496 Slice::Gen::MetaDataVisitor::visitStructEnd(const StructPtr&)
5497 {
5498 }
5499
5500 void
visitOperation(const OperationPtr & p)5501 Slice::Gen::MetaDataVisitor::visitOperation(const OperationPtr& p)
5502 {
5503 ClassDefPtr cl = ClassDefPtr::dynamicCast(p->container());
5504
5505 StringList metaData = p->getMetaData();
5506
5507 const UnitPtr ut = p->unit();
5508 const DefinitionContextPtr dc = ut->findDefinitionContext(p->file());
5509 assert(dc);
5510 if(!cl->isLocal() && p->hasMetaData("cpp:noexcept"))
5511 {
5512 dc->warning(InvalidMetaData, p->file(), p->line(), "ignoring metadata `cpp:noexcept' for non local interface");
5513 metaData.remove("cpp:noexcept");
5514 }
5515
5516 TypePtr returnType = p->returnType();
5517 if(!returnType)
5518 {
5519 for(StringList::const_iterator q = metaData.begin(); q != metaData.end();)
5520 {
5521 string s = *q++;
5522 if(s.find("cpp:type:") == 0 || s.find("cpp:view-type:") == 0 ||
5523 s.find("cpp:range") == 0 || s == "cpp:array")
5524 {
5525 dc->warning(InvalidMetaData, p->file(), p->line(),
5526 "ignoring invalid metadata `" + s + "' for operation with void return type");
5527 metaData.remove(s);
5528 }
5529 }
5530 }
5531 else
5532 {
5533 metaData = validate(returnType, metaData, p->file(), p->line(), true);
5534 }
5535
5536 p->setMetaData(metaData);
5537
5538 ParamDeclList params = p->parameters();
5539 for(ParamDeclList::iterator q = params.begin(); q != params.end(); ++q)
5540 {
5541 metaData = validate((*q)->type(), (*q)->getMetaData(), p->file(), (*q)->line(), true);
5542 (*q)->setMetaData(metaData);
5543 }
5544 }
5545
5546 void
visitDataMember(const DataMemberPtr & p)5547 Slice::Gen::MetaDataVisitor::visitDataMember(const DataMemberPtr& p)
5548 {
5549 StringList metaData = validate(p->type(), p->getMetaData(), p->file(), p->line());
5550 p->setMetaData(metaData);
5551 }
5552
5553 void
visitSequence(const SequencePtr & p)5554 Slice::Gen::MetaDataVisitor::visitSequence(const SequencePtr& p)
5555 {
5556 StringList metaData = validate(p, p->getMetaData(), p->file(), p->line());
5557 p->setMetaData(metaData);
5558 }
5559
5560 void
visitDictionary(const DictionaryPtr & p)5561 Slice::Gen::MetaDataVisitor::visitDictionary(const DictionaryPtr& p)
5562 {
5563 StringList metaData = validate(p, p->getMetaData(), p->file(), p->line());
5564 p->setMetaData(metaData);
5565 }
5566
5567 void
visitEnum(const EnumPtr & p)5568 Slice::Gen::MetaDataVisitor::visitEnum(const EnumPtr& p)
5569 {
5570 StringList metaData = validate(p, p->getMetaData(), p->file(), p->line());
5571 p->setMetaData(metaData);
5572 }
5573
5574 void
visitConst(const ConstPtr & p)5575 Slice::Gen::MetaDataVisitor::visitConst(const ConstPtr& p)
5576 {
5577 StringList metaData = validate(p, p->getMetaData(), p->file(), p->line());
5578 p->setMetaData(metaData);
5579 }
5580
5581 StringList
validate(const SyntaxTreeBasePtr & cont,const StringList & metaData,const string & file,const string & line,bool operation)5582 Slice::Gen::MetaDataVisitor::validate(const SyntaxTreeBasePtr& cont, const StringList& metaData,
5583 const string& file, const string& line, bool operation)
5584 {
5585 static const string cppPrefix = "cpp:";
5586 static const string cpp11Prefix = "cpp11:";
5587 static const string cpp98Prefix = "cpp98:";
5588
5589 const UnitPtr ut = cont->unit();
5590 const DefinitionContextPtr dc = ut->findDefinitionContext(file);
5591 assert(dc);
5592 StringList newMetaData = metaData;
5593 for(StringList::const_iterator p = newMetaData.begin(); p != newMetaData.end();)
5594 {
5595 string s = *p++;
5596
5597 string prefix;
5598 bool cpp98 = false;
5599 bool cpp11 = false;
5600
5601 if(s.find(cppPrefix) == 0)
5602 {
5603 prefix = cppPrefix;
5604 }
5605 else if(s.find(cpp98Prefix) == 0)
5606 {
5607 prefix = cpp98Prefix;
5608 cpp98 = true;
5609 }
5610 else if(s.find(cpp11Prefix) == 0)
5611 {
5612 prefix = cpp11Prefix;
5613 cpp11 = true;
5614 }
5615
5616 if(operation && (s == "cpp:const" || s == "cpp:noexcept"))
5617 {
5618 continue;
5619 }
5620
5621 if(!prefix.empty())
5622 {
5623 string ss = s.substr(prefix.size());
5624 if(ss == "type:wstring" || ss == "type:string")
5625 {
5626 BuiltinPtr builtin = BuiltinPtr::dynamicCast(cont);
5627 ModulePtr module = ModulePtr::dynamicCast(cont);
5628 ClassDefPtr clss = ClassDefPtr::dynamicCast(cont);
5629 StructPtr strct = StructPtr::dynamicCast(cont);
5630 ExceptionPtr exception = ExceptionPtr::dynamicCast(cont);
5631 if((builtin && builtin->kind() == Builtin::KindString) || module || clss || strct || exception)
5632 {
5633 continue;
5634 }
5635 }
5636 if(BuiltinPtr::dynamicCast(cont) && (ss.find("type:") == 0 || ss.find("view-type:") == 0))
5637 {
5638 if(BuiltinPtr::dynamicCast(cont)->kind() == Builtin::KindString)
5639 {
5640 continue;
5641 }
5642 }
5643 if(SequencePtr::dynamicCast(cont))
5644 {
5645 if(ss.find("type:") == 0 || ss.find("view-type:") == 0 || ss == "array" || ss.find("range") == 0)
5646 {
5647 continue;
5648 }
5649 }
5650 if(DictionaryPtr::dynamicCast(cont) && (ss.find("type:") == 0 || ss.find("view-type:") == 0))
5651 {
5652 continue;
5653 }
5654 if(!cpp11 && StructPtr::dynamicCast(cont) && (ss == "class" || ss == "comparable"))
5655 {
5656 continue;
5657 }
5658
5659 {
5660 ClassDefPtr cl = ClassDefPtr::dynamicCast(cont);
5661 if(cl && ((!cpp11 && ss == "virtual") ||
5662 (cl->isLocal() && ss.find("type:") == 0) ||
5663 (!cpp11 && cl->isLocal() && ss == "comparable")))
5664 {
5665 continue;
5666 }
5667 }
5668 if(ExceptionPtr::dynamicCast(cont) && ss == "ice_print")
5669 {
5670 continue;
5671 }
5672 if(!cpp11 && EnumPtr::dynamicCast(cont) && ss == "scoped")
5673 {
5674 continue;
5675 }
5676 if(!cpp98 && EnumPtr::dynamicCast(cont) && ss == "unscoped")
5677 {
5678 continue;
5679 }
5680
5681 {
5682 ClassDeclPtr cl = ClassDeclPtr::dynamicCast(cont);
5683 if(cl && cl->isLocal() && ss.find("type:") == 0)
5684 {
5685 continue;
5686 }
5687 }
5688
5689 dc->warning(InvalidMetaData, file, line, "ignoring invalid metadata `" + s + "'");
5690 newMetaData.remove(s);
5691 continue;
5692 }
5693
5694 if(s.find("delegate") == 0)
5695 {
5696 ClassDefPtr cl = ClassDefPtr::dynamicCast(cont);
5697 if(cl && cl->isDelegate())
5698 {
5699 continue;
5700 }
5701
5702 dc->warning(InvalidMetaData, file, line, "ignoring invalid metadata `" + s + "'");
5703 newMetaData.remove(s);
5704 continue;
5705 }
5706 }
5707 return newMetaData;
5708 }
5709
5710 void
normalizeMetaData(const UnitPtr & u,bool cpp11)5711 Slice::Gen::normalizeMetaData(const UnitPtr& u, bool cpp11)
5712 {
5713 NormalizeMetaDataVisitor visitor(cpp11);
5714 u->visit(&visitor, false);
5715 }
5716
NormalizeMetaDataVisitor(bool cpp11)5717 Slice::Gen::NormalizeMetaDataVisitor::NormalizeMetaDataVisitor(bool cpp11) :
5718 _cpp11(cpp11)
5719 {
5720 }
5721
5722 bool
visitUnitStart(const UnitPtr &)5723 Slice::Gen::NormalizeMetaDataVisitor::visitUnitStart(const UnitPtr&)
5724 {
5725 return true;
5726 }
5727
5728 bool
visitModuleStart(const ModulePtr & p)5729 Slice::Gen::NormalizeMetaDataVisitor::visitModuleStart(const ModulePtr& p)
5730 {
5731 p->setMetaData(normalize(p->getMetaData()));
5732 return true;
5733 }
5734
5735 void
visitModuleEnd(const ModulePtr &)5736 Slice::Gen::NormalizeMetaDataVisitor::visitModuleEnd(const ModulePtr&)
5737 {
5738 }
5739
5740 void
visitClassDecl(const ClassDeclPtr & p)5741 Slice::Gen::NormalizeMetaDataVisitor::visitClassDecl(const ClassDeclPtr& p)
5742 {
5743 p->setMetaData(normalize(p->getMetaData()));
5744 }
5745
5746 bool
visitClassDefStart(const ClassDefPtr & p)5747 Slice::Gen::NormalizeMetaDataVisitor::visitClassDefStart(const ClassDefPtr& p)
5748 {
5749 p->setMetaData(normalize(p->getMetaData()));
5750 return true;
5751 }
5752
5753 void
visitClassDefEnd(const ClassDefPtr &)5754 Slice::Gen::NormalizeMetaDataVisitor::visitClassDefEnd(const ClassDefPtr&)
5755 {
5756 }
5757
5758 bool
visitExceptionStart(const ExceptionPtr & p)5759 Slice::Gen::NormalizeMetaDataVisitor::visitExceptionStart(const ExceptionPtr& p)
5760 {
5761 p->setMetaData(normalize(p->getMetaData()));
5762 return true;
5763 }
5764
5765 void
visitExceptionEnd(const ExceptionPtr &)5766 Slice::Gen::NormalizeMetaDataVisitor::visitExceptionEnd(const ExceptionPtr&)
5767 {
5768 }
5769
5770 bool
visitStructStart(const StructPtr & p)5771 Slice::Gen::NormalizeMetaDataVisitor::visitStructStart(const StructPtr& p)
5772 {
5773 p->setMetaData(normalize(p->getMetaData()));
5774 return true;
5775 }
5776
5777 void
visitStructEnd(const StructPtr &)5778 Slice::Gen::NormalizeMetaDataVisitor::visitStructEnd(const StructPtr&)
5779 {
5780 }
5781
5782 void
visitOperation(const OperationPtr & p)5783 Slice::Gen::NormalizeMetaDataVisitor::visitOperation(const OperationPtr& p)
5784 {
5785 p->setMetaData(normalize(p->getMetaData()));
5786
5787 ParamDeclList params = p->parameters();
5788 for(ParamDeclList::iterator q = params.begin(); q != params.end(); ++q)
5789 {
5790 (*q)->setMetaData(normalize((*q)->getMetaData()));
5791 }
5792 }
5793
5794 void
visitDataMember(const DataMemberPtr & p)5795 Slice::Gen::NormalizeMetaDataVisitor::visitDataMember(const DataMemberPtr& p)
5796 {
5797 p->setMetaData(normalize(p->getMetaData()));
5798 }
5799
5800 void
visitSequence(const SequencePtr & p)5801 Slice::Gen::NormalizeMetaDataVisitor::visitSequence(const SequencePtr& p)
5802 {
5803 p->setMetaData(normalize(p->getMetaData()));
5804 }
5805
5806 void
visitDictionary(const DictionaryPtr & p)5807 Slice::Gen::NormalizeMetaDataVisitor::visitDictionary(const DictionaryPtr& p)
5808 {
5809 p->setMetaData(normalize(p->getMetaData()));
5810 }
5811
5812 void
visitEnum(const EnumPtr & p)5813 Slice::Gen::NormalizeMetaDataVisitor::visitEnum(const EnumPtr& p)
5814 {
5815 p->setMetaData(normalize(p->getMetaData()));
5816 }
5817
5818 void
visitConst(const ConstPtr & p)5819 Slice::Gen::NormalizeMetaDataVisitor::visitConst(const ConstPtr& p)
5820 {
5821 p->setMetaData(normalize(p->getMetaData()));
5822 }
5823
5824 StringList
normalize(const StringList & metaData)5825 Slice::Gen::NormalizeMetaDataVisitor::normalize(const StringList& metaData)
5826 {
5827 //
5828 // if _cpp11: transform "cpp:" into "cpp-all:" and "cpp"
5829 // + transform "cpp11:" into "cpp:" in front
5830 //
5831 // if !_cpp11: remove "cpp:", transform "cpp-all:" into "cpp"
5832 // + transform "cpp98:" into "cpp:" in front
5833
5834 //
5835 // Note: global metadata like header-ext exists only in cpp:
5836 // form and are not processed at all
5837 //
5838
5839 StringList result;
5840
5841 static const string cppPrefixTable[] =
5842 {
5843 "array",
5844 "class",
5845 "comparable",
5846 "const",
5847 "ice_print",
5848 "range",
5849 "scoped",
5850 "type:",
5851 "unscoped",
5852 "view-type:",
5853 "virtual",
5854 ""
5855 };
5856
5857 static const string cppPrefix = "cpp:";
5858 static const string cppAllPrefix = "cpp-all:";
5859
5860 //
5861 // First look for the higher priority cpp98/cpp11, that go to the
5862 // front of result
5863 //
5864
5865 static const string cpp11Prefix = "cpp11:";
5866 static const string cpp98Prefix = "cpp98:";
5867
5868 const string altCppPrefix = _cpp11 ? cpp11Prefix : cpp98Prefix;
5869
5870 for(StringList::const_iterator p = metaData.begin(); p != metaData.end(); ++p)
5871 {
5872 string s = *p;
5873
5874 unsigned int i = 0;
5875 bool found = false;
5876 while(!found)
5877 {
5878 string m = cppPrefixTable[i++];
5879 if(m.empty())
5880 {
5881 break;
5882 }
5883 if(s.find(altCppPrefix + m) == 0)
5884 {
5885 found = true;
5886 }
5887 }
5888
5889 if(found)
5890 {
5891 s.replace(0, altCppPrefix.length(), cppPrefix);
5892 result.push_back(s);
5893 }
5894 }
5895
5896 //
5897 // Then look for the lower-priority "cpp:" / "cpp-all:", pushed back later
5898 //
5899
5900 const string prefix = _cpp11 ? cppPrefix : cppAllPrefix;
5901
5902 for(StringList::const_iterator p = metaData.begin(); p != metaData.end(); ++p)
5903 {
5904 string s = *p;
5905
5906 unsigned int i = 0;
5907 bool foundPrefix = false;
5908 bool foundOld = false;
5909 while(!foundPrefix && !foundOld)
5910 {
5911 string m = cppPrefixTable[i++];
5912 if(m.empty())
5913 {
5914 break; // while
5915 }
5916 if(s.find(prefix + m) == 0)
5917 {
5918 foundPrefix = true;
5919 }
5920 else if(!_cpp11 && s.find(cppPrefix + m) == 0)
5921 {
5922 //
5923 // We want to filter-out "cpp:" when !_cpp11
5924 //
5925 foundOld = true;
5926 }
5927 }
5928
5929 if(foundPrefix)
5930 {
5931 if(_cpp11)
5932 {
5933 result.push_back(s);
5934 s.replace(0, prefix.length(), cppAllPrefix);
5935 result.push_back(s);
5936 }
5937 else
5938 {
5939 s.replace(0, prefix.length(), cppPrefix);
5940 result.push_back(s);
5941 }
5942 }
5943 else if(_cpp11 || !foundOld)
5944 {
5945 result.push_back(s);
5946 }
5947 }
5948
5949 return result;
5950 }
5951
5952 int
setUseWstring(ContainedPtr p,list<int> & hist,int use)5953 Slice::Gen::setUseWstring(ContainedPtr p, list<int>& hist, int use)
5954 {
5955 hist.push_back(use);
5956 StringList metaData = p->getMetaData();
5957 if(find(metaData.begin(), metaData.end(), "cpp:type:wstring") != metaData.end())
5958 {
5959 use = TypeContextUseWstring;
5960 }
5961 else if(find(metaData.begin(), metaData.end(), "cpp:type:string") != metaData.end())
5962 {
5963 use = 0;
5964 }
5965 return use;
5966 }
5967
5968 int
resetUseWstring(list<int> & hist)5969 Slice::Gen::resetUseWstring(list<int>& hist)
5970 {
5971 int use = hist.back();
5972 hist.pop_back();
5973 return use;
5974 }
5975
5976 string
getHeaderExt(const string & file,const UnitPtr & ut)5977 Slice::Gen::getHeaderExt(const string& file, const UnitPtr& ut)
5978 {
5979 string ext;
5980 static const string headerExtPrefix = "cpp:header-ext:";
5981 DefinitionContextPtr dc = ut->findDefinitionContext(file);
5982 assert(dc);
5983 string meta = dc->findMetaData(headerExtPrefix);
5984 if(meta.size() > headerExtPrefix.size())
5985 {
5986 ext = meta.substr(headerExtPrefix.size());
5987 }
5988 return ext;
5989 }
5990
5991 string
getSourceExt(const string & file,const UnitPtr & ut)5992 Slice::Gen::getSourceExt(const string& file, const UnitPtr& ut)
5993 {
5994 string ext;
5995 static const string sourceExtPrefix = "cpp:source-ext:";
5996 DefinitionContextPtr dc = ut->findDefinitionContext(file);
5997 assert(dc);
5998 string meta = dc->findMetaData(sourceExtPrefix);
5999 if(meta.size() > sourceExtPrefix.size())
6000 {
6001 ext = meta.substr(sourceExtPrefix.size());
6002 }
6003 return ext;
6004 }
6005
6006 // C++11 visitors
Cpp11DeclVisitor(Output & h,Output & c,const string & dllExport)6007 Slice::Gen::Cpp11DeclVisitor::Cpp11DeclVisitor(Output& h, Output& c, const string& dllExport) :
6008 H(h), C(c), _dllExport(dllExport)
6009 {
6010 }
6011
6012 bool
visitUnitStart(const UnitPtr & p)6013 Slice::Gen::Cpp11DeclVisitor::visitUnitStart(const UnitPtr& p)
6014 {
6015 if(!p->hasClassDecls() && !p->hasNonLocalExceptions())
6016 {
6017 return false;
6018 }
6019 C << sp << nl << "namespace" << nl << "{";
6020 return true;
6021 }
6022
6023 void
visitUnitEnd(const UnitPtr &)6024 Slice::Gen::Cpp11DeclVisitor::visitUnitEnd(const UnitPtr&)
6025 {
6026 C << sp << nl << "}";
6027 }
6028
6029 bool
visitModuleStart(const ModulePtr & p)6030 Slice::Gen::Cpp11DeclVisitor::visitModuleStart(const ModulePtr& p)
6031 {
6032 if(p->hasClassDecls())
6033 {
6034 H << sp << nl << "namespace " << fixKwd(p->name()) << nl << '{' << sp;
6035 }
6036 return true;
6037 }
6038
6039 void
visitModuleEnd(const ModulePtr & p)6040 Slice::Gen::Cpp11DeclVisitor::visitModuleEnd(const ModulePtr& p)
6041 {
6042 if(p->hasClassDecls())
6043 {
6044 H << sp << nl << '}';
6045 }
6046 }
6047
6048 void
visitClassDecl(const ClassDeclPtr & p)6049 Slice::Gen::Cpp11DeclVisitor::visitClassDecl(const ClassDeclPtr& p)
6050 {
6051 ClassDefPtr def = p->definition();
6052 if(def && def->isDelegate())
6053 {
6054 return;
6055 }
6056
6057 H << nl << "class " << fixKwd(p->name()) << ';';
6058 if(!p->isLocal() && (p->isInterface() || (def && !def->allOperations().empty())))
6059 {
6060 H << nl << "class " << p->name() << "Prx;";
6061 }
6062 }
6063
6064 bool
visitClassDefStart(const ClassDefPtr & p)6065 Slice::Gen::Cpp11DeclVisitor::visitClassDefStart(const ClassDefPtr& p)
6066 {
6067 if(p->isLocal())
6068 {
6069 return false;
6070 }
6071
6072 if(!p->isInterface())
6073 {
6074 C << sp;
6075
6076 C << nl << "const ::IceInternal::DefaultValueFactoryInit<" << fixKwd(p->scoped()) << "> ";
6077 C << "iceC" + p->flattenedScope() + p->name() + "_init" << "(\"" << p->scoped() << "\");";
6078
6079 if(p->compactId() >= 0)
6080 {
6081 string n = "iceC" + p->flattenedScope() + p->name() + "_compactIdInit ";
6082 C << nl << "const ::IceInternal::CompactIdInit " << n << "(\"" << p->scoped() << "\", " << p->compactId()
6083 << ");";
6084 }
6085 }
6086
6087 OperationList allOps = p->allOperations();
6088 if(p->isInterface() || !allOps.empty())
6089 {
6090 C << sp;
6091
6092 ClassList allBases = p->allBases();
6093 StringList ids;
6094 transform(allBases.begin(), allBases.end(), back_inserter(ids), ::IceUtil::constMemFun(&Contained::scoped));
6095 StringList other;
6096 other.push_back(p->scoped());
6097 other.push_back("::Ice::Object");
6098 other.sort();
6099 ids.merge(other);
6100 ids.unique();
6101
6102 C << nl << "const ::std::string iceC" << p->flattenedScope() << p->name() << "_ids[" << ids.size() << "] =";
6103 C << sb;
6104 for(StringList::const_iterator r = ids.begin(); r != ids.end();)
6105 {
6106 C << nl << '"' << *r << '"';
6107 if(++r != ids.end())
6108 {
6109 C << ',';
6110 }
6111 }
6112 C << eb << ';';
6113
6114 StringList allOpNames;
6115 transform(allOps.begin(), allOps.end(), back_inserter(allOpNames), ::IceUtil::constMemFun(&Contained::name));
6116 allOpNames.push_back("ice_id");
6117 allOpNames.push_back("ice_ids");
6118 allOpNames.push_back("ice_isA");
6119 allOpNames.push_back("ice_ping");
6120 allOpNames.sort();
6121 allOpNames.unique();
6122
6123 C << nl << "const ::std::string iceC" << p->flattenedScope() << p->name() << "_ops[] =";
6124 C << sb;
6125 for(StringList::const_iterator q = allOpNames.begin(); q != allOpNames.end();)
6126 {
6127 C << nl << '"' << *q << '"';
6128 if(++q != allOpNames.end())
6129 {
6130 C << ',';
6131 }
6132 }
6133 C << eb << ';';
6134 }
6135
6136 return true;
6137 }
6138
6139 bool
visitExceptionStart(const ExceptionPtr & p)6140 Slice::Gen::Cpp11DeclVisitor::visitExceptionStart(const ExceptionPtr& p)
6141 {
6142 if(p->isLocal())
6143 {
6144 return false;
6145 }
6146
6147 C << sp;
6148 C << nl << "const ::IceInternal::DefaultUserExceptionFactoryInit<" << fixKwd(p->scoped()) << "> ";
6149 C << "iceC" + p->flattenedScope() + p->name() + "_init" << "(\"" << p->scoped() << "\");";
6150 return false;
6151 }
6152
6153 void
visitOperation(const OperationPtr & p)6154 Slice::Gen::Cpp11DeclVisitor::visitOperation(const OperationPtr& p)
6155 {
6156 ClassDefPtr cl = ClassDefPtr::dynamicCast(p->container());
6157 if(cl && !cl->isLocal())
6158 {
6159 string flatName = "iceC" + p->flattenedScope() + p->name() + "_name";
6160 C << nl << "const ::std::string " << flatName << " = \"" << p->name() << "\";";
6161 }
6162 }
6163
Cpp11TypesVisitor(Output & h,Output & c,const string & dllExport)6164 Slice::Gen::Cpp11TypesVisitor::Cpp11TypesVisitor(Output& h, Output& c, const string& dllExport) :
6165 H(h), C(c), _dllExport(dllExport), _dllClassExport(toDllClassExport(dllExport)),
6166 _dllMemberExport(toDllMemberExport(dllExport)), _doneStaticSymbol(false), _useWstring(false)
6167 {
6168 }
6169
6170 bool
visitModuleStart(const ModulePtr & p)6171 Slice::Gen::Cpp11TypesVisitor::visitModuleStart(const ModulePtr& p)
6172 {
6173 if(!p->hasOtherConstructedOrExceptions())
6174 {
6175 return false;
6176 }
6177
6178 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
6179 H << sp << nl << "namespace " << fixKwd(p->name()) << nl << '{';
6180 return true;
6181 }
6182
6183 void
visitModuleEnd(const ModulePtr & p)6184 Slice::Gen::Cpp11TypesVisitor::visitModuleEnd(const ModulePtr& p)
6185 {
6186 if(p->hasStructs())
6187 {
6188 H << sp << nl << "using Ice::operator<;";
6189 H << nl << "using Ice::operator<=;";
6190 H << nl << "using Ice::operator>;";
6191 H << nl << "using Ice::operator>=;";
6192 H << nl << "using Ice::operator==;";
6193 H << nl << "using Ice::operator!=;";
6194 }
6195 H << sp << nl << '}';
6196 _useWstring = resetUseWstring(_useWstringHist);
6197 }
6198
6199 bool
visitClassDefStart(const ClassDefPtr &)6200 Slice::Gen::Cpp11TypesVisitor::visitClassDefStart(const ClassDefPtr&)
6201 {
6202 return false;
6203 }
6204
6205 bool
visitExceptionStart(const ExceptionPtr & p)6206 Slice::Gen::Cpp11TypesVisitor::visitExceptionStart(const ExceptionPtr& p)
6207 {
6208 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
6209
6210 string name = fixKwd(p->name());
6211 string scope = fixKwd(p->scope());
6212 string scoped = fixKwd(p->scoped());
6213 ExceptionPtr base = p->base();
6214 DataMemberList dataMembers = p->dataMembers();
6215 DataMemberList allDataMembers = p->allDataMembers();
6216 DataMemberList baseDataMembers;
6217
6218 vector<string> params;
6219 vector<string> allParamDecls;
6220 vector<string> baseParams;
6221 map<string, CommentPtr> allComments;
6222
6223 string fileParam = "file";
6224 string lineParam = "line";
6225
6226 for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
6227 {
6228 params.push_back(fixKwd((*q)->name()));
6229 }
6230
6231 for(DataMemberList::const_iterator q = allDataMembers.begin(); q != allDataMembers.end(); ++q)
6232 {
6233 string typeName = inputTypeToString((*q)->type(), (*q)->optional(), scope, (*q)->getMetaData(),
6234 _useWstring | TypeContextCpp11);
6235 allParamDecls.push_back(typeName + " " + fixKwd((*q)->name()));
6236
6237 CommentPtr comment = (*q)->parseComment(false);
6238 if(comment)
6239 {
6240 allComments[(*q)->name()] = comment;
6241 }
6242
6243 if((*q)->name() == "file")
6244 {
6245 fileParam = "file_";
6246 }
6247 else if((*q)->name() == "line")
6248 {
6249 fileParam = "line_";
6250 }
6251 }
6252
6253 if(base)
6254 {
6255 baseDataMembers = base->allDataMembers();
6256 for(DataMemberList::const_iterator q = baseDataMembers.begin(); q != baseDataMembers.end(); ++q)
6257 {
6258 baseParams.push_back(fixKwd((*q)->name()));
6259 }
6260 }
6261
6262 string helperClass =
6263 getUnqualified(p->isLocal() ? "::Ice::LocalExceptionHelper" : "::Ice::UserExceptionHelper", scope);
6264 string baseClass = base ?
6265 getUnqualified(fixKwd(base->scoped()), scope) :
6266 getUnqualified(p->isLocal() ? "::Ice::LocalException" : "::Ice::UserException", scope);
6267 string templateParameters = name + ", " + baseClass;
6268
6269 H << sp;
6270 writeDocSummary(H, p);
6271 H << nl << "class " << _dllClassExport << name << " : public " << helperClass << "<" << templateParameters << ">";
6272 H << sb;
6273
6274 H.dec();
6275 H << nl << "public:";
6276 H.inc();
6277
6278 // Out of line dtor to avoid weak vtable
6279 H << sp << nl << _dllMemberExport << "virtual ~" << name << "();";
6280
6281 // Default copy ctor
6282 H << sp << nl << name << "(const " << name << "&) = default;";
6283
6284 C << sp;
6285 C << nl << scoped.substr(2) << "::~" << name << "()";
6286 C << sb;
6287 C << eb;
6288
6289 if(p->isLocal())
6290 {
6291 H << sp;
6292 H << nl << "/**";
6293 H << nl << " * The file and line number are required for all local exceptions.";
6294 H << nl << " * @param " << fileParam
6295 << " The file name in which the exception was raised, typically __FILE__.";
6296 H << nl << " * @param " << lineParam
6297 << " The line number at which the exception was raised, typically __LINE__.";
6298 H << nl << " */";
6299 H << nl << name << "(const char* " << fileParam << ", int " << lineParam << ") : ";
6300 H << getUnqualified("::Ice::LocalExceptionHelper", scope) << "<" << templateParameters << ">";
6301 H << "(" << fileParam << ", " << lineParam << ")";
6302 H << sb;
6303 H << eb;
6304 }
6305 else
6306 {
6307 H << sp << nl << name << "() = default;";
6308 }
6309
6310 if(!allDataMembers.empty())
6311 {
6312 H << sp;
6313 H << nl << "/**";
6314 H << nl << " * One-shot constructor to initialize all data members.";
6315 if(p->isLocal())
6316 {
6317 H << nl << " * The file and line number are required for all local exceptions.";
6318 H << nl << " * @param " << fileParam
6319 << " The file name in which the exception was raised, typically __FILE__.";
6320 H << nl << " * @param " << lineParam
6321 << " The line number at which the exception was raised, typically __LINE__.";
6322 }
6323 for(DataMemberList::const_iterator q = allDataMembers.begin(); q != allDataMembers.end(); ++q)
6324 {
6325 map<string, CommentPtr>::iterator r = allComments.find((*q)->name());
6326 if(r != allComments.end())
6327 {
6328 H << nl << " * @param " << fixKwd(r->first) << " " << getDocSentence(r->second->overview());
6329 }
6330 }
6331 H << nl << " */";
6332 H << nl << name << "(";
6333 if(p->isLocal())
6334 {
6335 H << "const char* " << fileParam << ", int " << lineParam;
6336 if(!allParamDecls.empty())
6337 {
6338 H << ", ";
6339 }
6340 }
6341
6342 for(vector<string>::const_iterator q = allParamDecls.begin(); q != allParamDecls.end(); ++q)
6343 {
6344 if(q != allParamDecls.begin())
6345 {
6346 H << ", ";
6347 }
6348 H << (*q);
6349 }
6350 H << ") :";
6351 H.inc();
6352 if(base && (p->isLocal() || !baseDataMembers.empty()))
6353 {
6354 H << nl << helperClass << "<" << templateParameters << ">" << "(";
6355 if(p->isLocal())
6356 {
6357 H << fileParam << ", " << lineParam;
6358 if(!baseDataMembers.empty())
6359 {
6360 H << ", ";
6361 }
6362 }
6363
6364 for(DataMemberList::const_iterator q = baseDataMembers.begin(); q != baseDataMembers.end(); ++q)
6365 {
6366 if(q != baseDataMembers.begin())
6367 {
6368 H << ", ";
6369 }
6370 if(isMovable((*q)->type()))
6371 {
6372 H << "::std::move(" << fixKwd((*q)->name()) << ")";
6373 }
6374 else
6375 {
6376 H << fixKwd((*q)->name());
6377 }
6378 }
6379
6380 H << ")";
6381 if(!dataMembers.empty())
6382 {
6383 H << ",";
6384 }
6385 }
6386 else if(p->isLocal())
6387 {
6388 H << " " << getUnqualified("::Ice::LocalExceptionHelper", scope) << "<" << templateParameters << ">";
6389 H << "(" << fileParam << ", " << lineParam << ")";
6390 if(!dataMembers.empty())
6391 {
6392 H << ",";
6393 }
6394 }
6395
6396 for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
6397 {
6398 string memberName = fixKwd((*q)->name());
6399 if(q != dataMembers.begin())
6400 {
6401 H << ",";
6402 }
6403 if(isMovable((*q)->type()))
6404 {
6405 H << nl << memberName << "(::std::move(" << memberName << "))";
6406 }
6407 else
6408 {
6409 H << nl << memberName << "(" << memberName << ")";
6410 }
6411 }
6412
6413 H.dec();
6414 H << sb;
6415 H << eb;
6416 }
6417
6418 H << sp;
6419 H << nl << "/**";
6420 H << nl << " * Obtains a tuple containing all of the exception's data members.";
6421 H << nl << " * @return The data members in a tuple.";
6422 H << nl << " */";
6423 writeIceTuple(H, scope, p->allDataMembers(), _useWstring);
6424
6425 H << sp;
6426 H << nl << "/**";
6427 H << nl << " * Obtains the Slice type ID of this exception.";
6428 H << nl << " * @return The fully-scoped type ID.";
6429 H << nl << " */";
6430 H << nl << _dllMemberExport << "static const ::std::string& ice_staticId();";
6431
6432 C << sp << nl << "const ::std::string&" << nl << scoped.substr(2) << "::ice_staticId()";
6433 C << sb;
6434 //
6435 // Use local static so that ice_staticId() is usable during static construction.
6436 //
6437 C << nl << "static const ::std::string typeId = \"" << p->scoped() << "\";";
6438 C << nl << "return typeId;";
6439 C << eb;
6440
6441 StringList metaData = p->getMetaData();
6442 if(find(metaData.begin(), metaData.end(), "cpp:ice_print") != metaData.end())
6443 {
6444 H << nl << "/**";
6445 H << nl << " * Prints this exception to the given stream.";
6446 H << nl << " * @param stream The target stream.";
6447 H << nl << " */";
6448 H << nl << _dllMemberExport << "virtual void ice_print(::std::ostream& stream) const override;";
6449 }
6450
6451 if(!p->isLocal() && p->usesClasses(false))
6452 {
6453 if(!base || (base && !base->usesClasses(false)))
6454 {
6455 H << sp;
6456 H << nl << "/// \\cond STREAM";
6457 H << nl << _dllMemberExport << "virtual bool _usesClasses() const override;";
6458 H << nl << "/// \\endcond";
6459
6460 C << sp;
6461 C << nl << "/// \\cond STREAM";
6462 C << nl << "bool";
6463 C << nl << scoped.substr(2) << "::_usesClasses() const";
6464 C << sb;
6465 C << nl << "return true;";
6466 C << eb;
6467 C << nl << "/// \\endcond";
6468 }
6469 }
6470
6471 if(!dataMembers.empty())
6472 {
6473 H << sp;
6474 }
6475 return true;
6476 }
6477
6478 void
visitExceptionEnd(const ExceptionPtr & p)6479 Slice::Gen::Cpp11TypesVisitor::visitExceptionEnd(const ExceptionPtr& p)
6480 {
6481 string name = fixKwd(p->name());
6482 string scope = fixKwd(p->scope());
6483 string scoped = fixKwd(p->scoped());
6484 string factoryName;
6485
6486 if(!p->isLocal())
6487 {
6488 ExceptionPtr base = p->base();
6489 bool basePreserved = p->inheritsMetaData("preserve-slice");
6490 bool preserved = p->hasMetaData("preserve-slice");
6491
6492 if(preserved && !basePreserved)
6493 {
6494 H << sp;
6495 H << nl << "/**";
6496 H << nl << " * Obtains the SlicedData object created when an unknown exception type was marshaled";
6497 H << nl << " * in the sliced format and the Ice run time sliced it to a known type.";
6498 H << nl << " * @return The SlicedData object, or nil if the exception was not sliced or was not";
6499 H << nl << " * marshaled in the sliced format.";
6500 H << nl << " */";
6501 H << nl << _dllMemberExport << "virtual ::std::shared_ptr<" << getUnqualified("::Ice::SlicedData", scope)
6502 << "> ice_getSlicedData() const override;";
6503 H << sp;
6504 H << nl << "/// \\cond STREAM";
6505 H << nl << _dllMemberExport << "virtual void _write(" << getUnqualified("::Ice::OutputStream*", scope)
6506 << ") const override;";
6507 H << nl << _dllMemberExport << "virtual void _read(" << getUnqualified("::Ice::InputStream*", scope)
6508 << ") override;";
6509
6510 H << sp << nl << "::std::shared_ptr<" << getUnqualified("::Ice::SlicedData", scope) << "> _slicedData;";
6511 H << nl << "/// \\endcond";
6512
6513 C << sp;
6514 C << nl << "::std::shared_ptr<::Ice::SlicedData>" << nl << scoped.substr(2)
6515 << "::ice_getSlicedData() const";
6516 C << sb;
6517 C << nl << "return _slicedData;";
6518 C << eb;
6519
6520 C << sp;
6521 C << nl << "/// \\cond STREAM";
6522 C << nl << "void" << nl << scoped.substr(2) << "::_write("
6523 << getUnqualified("::Ice::OutputStream*", scope) << " ostr) const";
6524 C << sb;
6525 C << nl << "ostr->startException(_slicedData);";
6526 C << nl << "_writeImpl(ostr);";
6527 C << nl << "ostr->endException();";
6528 C << eb;
6529
6530 C << sp << nl << "void" << nl << scoped.substr(2) << "::_read("
6531 << getUnqualified("::Ice::InputStream*", scope) << " istr)";
6532 C << sb;
6533 C << nl << "istr->startException();";
6534 C << nl << "_readImpl(istr);";
6535 C << nl << "_slicedData = istr->endException(true);";
6536 C << eb;
6537 C << nl << "/// \\endcond";
6538 }
6539 }
6540 H << eb << ';';
6541
6542 if(!p->isLocal())
6543 {
6544 //
6545 // We need an instance here to trigger initialization if the implementation is in a shared libarry.
6546 // But we do this only once per source file, because a single instance is sufficient to initialize
6547 // all of the globals in a shared library.
6548 //
6549 if(!_doneStaticSymbol)
6550 {
6551 _doneStaticSymbol = true;
6552 H << sp;
6553 H << nl << "/// \\cond INTERNAL";
6554 H << nl << "static " << name << " _iceS_" << p->name() << "_init;";
6555 H << nl << "/// \\endcond";
6556 }
6557 }
6558
6559 _useWstring = resetUseWstring(_useWstringHist);
6560 }
6561
6562 bool
visitStructStart(const StructPtr & p)6563 Slice::Gen::Cpp11TypesVisitor::visitStructStart(const StructPtr& p)
6564 {
6565 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
6566
6567 H << sp;
6568 writeDocSummary(H, p);
6569 H << nl << "struct " << fixKwd(p->name());
6570 H << sb;
6571
6572 return true;
6573 }
6574
6575 void
visitStructEnd(const StructPtr & p)6576 Slice::Gen::Cpp11TypesVisitor::visitStructEnd(const StructPtr& p)
6577 {
6578 H << sp;
6579 H << nl << "/**";
6580 H << nl << " * Obtains a tuple containing all of the exception's data members.";
6581 H << nl << " * @return The data members in a tuple.";
6582 H << nl << " */";
6583 writeIceTuple(H, fixKwd(p->scope()), p->dataMembers(), _useWstring);
6584 H << eb << ';';
6585 _useWstring = resetUseWstring(_useWstringHist);
6586 }
6587
6588 void
visitDataMember(const DataMemberPtr & p)6589 Slice::Gen::Cpp11TypesVisitor::visitDataMember(const DataMemberPtr& p)
6590 {
6591 string scope = fixKwd(ContainedPtr::dynamicCast(p->container())->scope());
6592 string name = fixKwd(p->name());
6593 writeDocSummary(H, p);
6594 H << nl << typeToString(p->type(), p->optional(), scope, p->getMetaData(), _useWstring | TypeContextCpp11)
6595 << ' ' << name;
6596
6597 string defaultValue = p->defaultValue();
6598 if(!defaultValue.empty())
6599 {
6600 BuiltinPtr builtin = BuiltinPtr::dynamicCast(p->type());
6601 if(p->optional() && builtin->kind() == Builtin::KindString)
6602 {
6603 //
6604 // = "<string literal>" doesn't work for optional<std::string>
6605 //
6606 H << '{';
6607 writeConstantValue(H, p->type(), p->defaultValueType(), defaultValue, _useWstring | TypeContextCpp11,
6608 p->getMetaData(), scope);
6609 H << '}';
6610 }
6611 else
6612 {
6613 H << " = ";
6614 writeConstantValue(H, p->type(), p->defaultValueType(), defaultValue, _useWstring | TypeContextCpp11,
6615 p->getMetaData(), scope);
6616 }
6617 }
6618
6619 H << ';';
6620 }
6621
6622 void
visitSequence(const SequencePtr & p)6623 Slice::Gen::Cpp11TypesVisitor::visitSequence(const SequencePtr& p)
6624 {
6625 string name = fixKwd(p->name());
6626 string scope = fixKwd(p->scope());
6627 TypePtr type = p->type();
6628 int typeCtx = p->isLocal() ? (_useWstring | TypeContextLocal) : _useWstring;
6629 string s = typeToString(type, scope, p->typeMetaData(), typeCtx | TypeContextCpp11);
6630 StringList metaData = p->getMetaData();
6631
6632 string seqType = findMetaData(metaData, _useWstring);
6633 H << sp;
6634 writeDocSummary(H, p);
6635
6636 if(!seqType.empty())
6637 {
6638 H << nl << "using " << name << " = " << seqType << ';';
6639 }
6640 else
6641 {
6642 H << nl << "using " << name << " = ::std::vector<" << s << ">;";
6643 }
6644 }
6645
6646 void
visitDictionary(const DictionaryPtr & p)6647 Slice::Gen::Cpp11TypesVisitor::visitDictionary(const DictionaryPtr& p)
6648 {
6649 string name = fixKwd(p->name());
6650 string scope = fixKwd(p->scope());
6651 string dictType = findMetaData(p->getMetaData());
6652 int typeCtx = p->isLocal() ? (_useWstring | TypeContextLocal) : _useWstring;
6653
6654 H << sp;
6655 writeDocSummary(H, p);
6656
6657 if(dictType.empty())
6658 {
6659 //
6660 // A default std::map dictionary
6661 //
6662 TypePtr keyType = p->keyType();
6663 TypePtr valueType = p->valueType();
6664 string ks = typeToString(keyType, scope, p->keyMetaData(), typeCtx | TypeContextCpp11);
6665 string vs = typeToString(valueType, scope, p->valueMetaData(), typeCtx | TypeContextCpp11);
6666
6667 H << nl << "using " << name << " = ::std::map<" << ks << ", " << vs << ">;";
6668 }
6669 else
6670 {
6671 //
6672 // A custom dictionary
6673 //
6674 H << nl << "using " << name << " = " << dictType << ';';
6675 }
6676 }
6677
Cpp11ProxyVisitor(Output & h,Output & c,const string & dllExport)6678 Slice::Gen::Cpp11ProxyVisitor::Cpp11ProxyVisitor(Output& h, Output& c, const string& dllExport) :
6679 H(h), C(c), _dllClassExport(toDllClassExport(dllExport)),
6680 _dllMemberExport(toDllMemberExport(dllExport)),
6681 _useWstring(false)
6682 {
6683 }
6684
6685 bool
visitUnitStart(const UnitPtr &)6686 Slice::Gen::Cpp11ProxyVisitor::visitUnitStart(const UnitPtr&)
6687 {
6688 return true;
6689 }
6690
6691 void
visitUnitEnd(const UnitPtr &)6692 Slice::Gen::Cpp11ProxyVisitor::visitUnitEnd(const UnitPtr&)
6693 {
6694 }
6695
6696 bool
visitModuleStart(const ModulePtr & p)6697 Slice::Gen::Cpp11ProxyVisitor::visitModuleStart(const ModulePtr& p)
6698 {
6699 if(!p->hasNonLocalClassDefs())
6700 {
6701 return false;
6702 }
6703
6704 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
6705
6706 H << sp << nl << "namespace " << fixKwd(p->name()) << nl << '{';
6707 return true;
6708 }
6709
6710 void
visitModuleEnd(const ModulePtr &)6711 Slice::Gen::Cpp11ProxyVisitor::visitModuleEnd(const ModulePtr&)
6712 {
6713 H << sp << nl << '}';
6714
6715 _useWstring = resetUseWstring(_useWstringHist);
6716 }
6717
6718 bool
visitClassDefStart(const ClassDefPtr & p)6719 Slice::Gen::Cpp11ProxyVisitor::visitClassDefStart(const ClassDefPtr& p)
6720 {
6721 if(p->isLocal() || (!p->isInterface() && p->allOperations().empty()))
6722 {
6723 return false;
6724 }
6725
6726 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
6727
6728 string name = fixKwd(p->name());
6729 string scope = fixKwd(p->scope());
6730 string scoped = fixKwd(p->scoped());
6731 ClassList bases = p->bases();
6732
6733 ClassDefPtr base;
6734 if(!bases.empty() && !bases.front()->isInterface())
6735 {
6736 base = bases.front();
6737 }
6738
6739 H << sp;
6740 writeDocSummary(H, p);
6741 H << nl << "class " << _dllClassExport << p->name() << "Prx : public virtual "
6742 << getUnqualified("::Ice::Proxy", scope) << "<" << fixKwd(p->name() + "Prx") << ", ";
6743 if(bases.empty() || (base && base->allOperations().empty()))
6744 {
6745 H << getUnqualified("::Ice::ObjectPrx", scope);
6746 }
6747 else
6748 {
6749 ClassList::const_iterator q = bases.begin();
6750 while(q != bases.end())
6751 {
6752 H << getUnqualified(fixKwd((*q)->scoped() + "Prx"), scope);
6753 if(++q != bases.end())
6754 {
6755 H << ", ";
6756 }
6757 }
6758 }
6759 H << ">";
6760
6761 H << sb;
6762 H.dec();
6763 H << nl << "public:";
6764 H.inc();
6765 return true;
6766 }
6767
6768 void
visitClassDefEnd(const ClassDefPtr & p)6769 Slice::Gen::Cpp11ProxyVisitor::visitClassDefEnd(const ClassDefPtr& p)
6770 {
6771 string prx = fixKwd(p->name() + "Prx");
6772 const string suffix = p->isInterface() ? "" : "Disp";
6773 const string scoped = fixKwd(p->scoped() + "Prx");
6774 const string scope = fixKwd(p->scope());
6775
6776 H << sp;
6777 H << nl << "/**";
6778 H << nl << " * Obtains the Slice type ID of this " << (p->isInterface() ? "interface" : "class") << ".";
6779 H << nl << " * @return The fully-scoped type ID.";
6780 H << nl << " */";
6781 H << nl << _dllMemberExport << "static const ::std::string& ice_staticId();";
6782
6783 H.dec();
6784 H << sp << nl << "protected:";
6785 H.inc();
6786 H << sp;
6787 H << nl << "/// \\cond INTERNAL";
6788 H << nl << getUnqualified(prx, scope) << "() = default;";
6789 H << nl << "friend ::std::shared_ptr<" << getUnqualified(prx, scope) << "> IceInternal::createProxy<"
6790 << getUnqualified(prx, scope) << ">();";
6791 H << sp;
6792 H << nl << _dllMemberExport << "virtual ::std::shared_ptr<" << getUnqualified("::Ice::ObjectPrx", scope)
6793 << "> _newInstance() const override;";
6794 H << nl << "/// \\endcond";
6795 H << eb << ';';
6796
6797 C << sp;
6798 C << nl << "/// \\cond INTERNAL";
6799 C << nl << "::std::shared_ptr<::Ice::ObjectPrx>";
6800 C << nl << scoped.substr(2) << "::_newInstance() const";
6801 C << sb;
6802 C << nl << "return ::IceInternal::createProxy<" << getUnqualified(prx, scope) << ">();";
6803 C << eb;
6804 C << nl << "/// \\endcond";
6805 C << sp;
6806 C << nl << "const ::std::string&" << nl << scoped.substr(2) << "::ice_staticId()";
6807 C << sb;
6808 C << nl << "return "<< fixKwd(p->name() + suffix) << "::ice_staticId();";
6809 C << eb;
6810
6811 _useWstring = resetUseWstring(_useWstringHist);
6812 }
6813
6814 void
visitOperation(const OperationPtr & p)6815 Slice::Gen::Cpp11ProxyVisitor::visitOperation(const OperationPtr& p)
6816 {
6817 string name = p->name();
6818 string flatName = "iceC" + p->flattenedScope() + p->name() + "_name";
6819
6820 ContainerPtr container = p->container();
6821 ClassDefPtr cl = ClassDefPtr::dynamicCast(container);
6822 string clScope = fixKwd(cl->scope());
6823
6824 TypePtr ret = p->returnType();
6825
6826 bool retIsOpt = p->returnIsOptional();
6827 string retS = returnTypeToString(ret, retIsOpt, clScope, p->getMetaData(), _useWstring | TypeContextCpp11);
6828
6829 vector<string> params;
6830 vector<string> paramsDecl;
6831
6832 vector<string> inParamsS;
6833 vector<string> inParamsDecl;
6834 vector<string> inParamsImplDecl;
6835
6836 vector<string> futureOutParams;
6837 vector<string> lambdaOutParams;
6838
6839 ParamDeclList paramList = p->parameters();
6840 ParamDeclList inParams = p->inParameters();
6841 ParamDeclList outParams = p->outParameters();
6842
6843 string returnValueS = "returnValue";
6844 bool outParamsHasOpt = false;
6845
6846 if(ret)
6847 {
6848 futureOutParams.push_back(typeToString(ret, retIsOpt, clScope, p->getMetaData(), _useWstring |
6849 TypeContextCpp11));
6850
6851 lambdaOutParams.push_back(typeToString(ret, retIsOpt, clScope, p->getMetaData(), _useWstring |
6852 TypeContextInParam | TypeContextCpp11));
6853
6854 outParamsHasOpt |= p->returnIsOptional();
6855 }
6856
6857 for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
6858 {
6859 string paramName = fixKwd((*q)->name());
6860 StringList metaData = (*q)->getMetaData();
6861
6862 if((*q)->isOutParam())
6863 {
6864 futureOutParams.push_back(typeToString((*q)->type(), (*q)->optional(), clScope, metaData,
6865 _useWstring | TypeContextCpp11));
6866 lambdaOutParams.push_back(typeToString((*q)->type(), (*q)->optional(), clScope, metaData,
6867 _useWstring | TypeContextInParam | TypeContextCpp11));
6868
6869 string outputTypeString = outputTypeToString((*q)->type(), (*q)->optional(), clScope, metaData,
6870 _useWstring | TypeContextCpp11);
6871
6872 params.push_back(outputTypeString);
6873 paramsDecl.push_back(outputTypeString + ' ' + paramName);
6874
6875 outParamsHasOpt |= (*q)->optional();
6876
6877 if((*q)->name() == "returnValue")
6878 {
6879 returnValueS = "_returnValue";
6880 }
6881 }
6882 else
6883 {
6884 string typeString = inputTypeToString((*q)->type(), (*q)->optional(), clScope, metaData,
6885 _useWstring | TypeContextCpp11);
6886
6887 params.push_back(typeString);
6888 paramsDecl.push_back(typeString + ' ' + paramName);
6889
6890 inParamsS.push_back(typeString);
6891 inParamsDecl.push_back(typeString + ' ' + paramName);
6892 inParamsImplDecl.push_back(typeString + ' ' + paramPrefix + (*q)->name());
6893 }
6894 }
6895
6896 string scoped = fixKwd(cl->scope() + cl->name() + "Prx" + "::").substr(2);
6897
6898 const string contextParam = escapeParam(paramList, "context");
6899 const string contextDecl = "const " + getUnqualified("::Ice::Context&", clScope) + " " + contextParam + " = " +
6900 getUnqualified("::Ice::noExplicitContext", clScope);
6901
6902 string futureT;
6903 if(futureOutParams.empty())
6904 {
6905 futureT = "void";
6906 }
6907 else if(futureOutParams.size() == 1)
6908 {
6909 futureT = futureOutParams[0];
6910 }
6911 else
6912 {
6913 futureT = resultStructName(name, fixKwd(cl->name()));
6914 }
6915
6916 const string deprecateSymbol = getDeprecateSymbol(p, cl);
6917
6918 CommentPtr comment = p->parseComment(false);
6919 const string contextDoc = "@param " + contextParam + " The Context map to send with the invocation.";
6920 const string futureDoc = "The future object for the invocation.";
6921
6922 //
6923 // Synchronous operation
6924 //
6925 H << sp;
6926 if(comment)
6927 {
6928 StringList postParams;
6929 postParams.push_back(contextDoc);
6930 writeOpDocSummary(H, p, comment, OpDocAllParams, true, StringList(), postParams, comment->returns());
6931 }
6932 H << nl << deprecateSymbol << retS << ' ' << fixKwd(name) << spar << paramsDecl << contextDecl << epar;
6933 H << sb;
6934 H << nl;
6935 if(futureOutParams.size() == 1)
6936 {
6937 if(ret)
6938 {
6939 H << "return ";
6940 }
6941 else
6942 {
6943 H << fixKwd((*outParams.begin())->name()) << " = ";
6944 }
6945 }
6946 else if(futureOutParams.size() > 1)
6947 {
6948 H << "auto _result = ";
6949 }
6950
6951 H << "_makePromiseOutgoing<" << getUnqualified(futureT, cl->scoped()) << ">";
6952
6953 H << spar << "true, this" << "&" + cl->name() + "Prx::_iceI_" + name;
6954 for(ParamDeclList::const_iterator q = inParams.begin(); q != inParams.end(); ++q)
6955 {
6956 H << fixKwd((*q)->name());
6957 }
6958 H << contextParam << epar << ".get();";
6959 if(futureOutParams.size() > 1)
6960 {
6961 for(ParamDeclList::const_iterator q = outParams.begin(); q != outParams.end(); ++q)
6962 {
6963 H << nl << fixKwd((*q)->name()) << " = ";
6964 H << condMove(isMovable((*q)->type()), "_result." + fixKwd((*q)->name())) + ";";
6965 }
6966 if(ret)
6967 {
6968 H << nl << "return " + condMove(isMovable(ret), "_result." + returnValueS) + ";";
6969 }
6970 }
6971 H << eb;
6972
6973 //
6974 // Promise based asynchronous operation
6975 //
6976 H << sp;
6977 if(comment)
6978 {
6979 StringList postParams, returns;
6980 postParams.push_back(contextDoc);
6981 returns.push_back(futureDoc);
6982 writeOpDocSummary(H, p, comment, OpDocInParams, false, StringList(), postParams, returns);
6983 }
6984 H << nl << "template<template<typename> class P = ::std::promise>";
6985 H << nl << deprecateSymbol << "auto " << name << "Async" << spar << inParamsDecl << contextDecl << epar;
6986 H.inc();
6987 H << nl << "-> decltype(::std::declval<P<" << futureT << ">>().get_future())";
6988 H.dec();
6989 H << sb;
6990
6991 H << nl << "return _makePromiseOutgoing<" << futureT << ", P>" << spar;
6992
6993 H << "false, this" << string("&" + cl->name() + "Prx::_iceI_" + name);
6994 for(ParamDeclList::const_iterator q = inParams.begin(); q != inParams.end(); ++q)
6995 {
6996 H << fixKwd((*q)->name());
6997 }
6998 H << contextParam << epar << ";";
6999 H << eb;
7000
7001 //
7002 // Lambda based asynchronous operation
7003 //
7004 bool lambdaCustomOut = (lambdaOutParams != futureOutParams);
7005
7006 const string responseParam = escapeParam(inParams, "response");
7007 const string exParam = escapeParam(inParams, "ex");
7008 const string sentParam = escapeParam(inParams, "sent");
7009
7010 H << sp;
7011 if(comment)
7012 {
7013 StringList postParams, returns;
7014 postParams.push_back("@param " + responseParam + " The response callback.");
7015 postParams.push_back("@param " + exParam + " The exception callback.");
7016 postParams.push_back("@param " + sentParam + " The sent callback.");
7017 postParams.push_back(contextDoc);
7018 returns.push_back("A function that can be called to cancel the invocation locally.");
7019 writeOpDocSummary(H, p, comment, OpDocInParams, false, StringList(), postParams, returns);
7020 }
7021 H << nl;
7022 if(lambdaCustomOut)
7023 {
7024 H << _dllMemberExport;
7025 }
7026 H << "::std::function<void()>";
7027 H << nl << name << "Async(";
7028 H.useCurrentPosAsIndent();
7029 if(!inParamsDecl.empty())
7030 {
7031 if(lambdaCustomOut)
7032 {
7033 for(vector<string>::const_iterator q = inParamsS.begin(); q != inParamsS.end(); ++q)
7034 {
7035 if(q != inParamsS.begin())
7036 {
7037 H << " ";
7038 }
7039
7040 H << *q << ",";
7041 }
7042 }
7043 else
7044 {
7045 for(vector<string>::const_iterator q = inParamsDecl.begin(); q != inParamsDecl.end(); ++q)
7046 {
7047 if(q != inParamsDecl.begin())
7048 {
7049 H << " ";
7050 }
7051
7052 H << *q << ",";
7053 }
7054 }
7055 H << nl;
7056 }
7057
7058 H << "::std::function<void" << spar << lambdaOutParams << epar << "> " << responseParam << ",";
7059 H << nl << "::std::function<void(::std::exception_ptr)> " << exParam << " = nullptr,";
7060 H << nl << "::std::function<void(bool)> " << sentParam << " = nullptr,";
7061 H << nl << contextDecl << ")" << string(lambdaCustomOut ? ";" : "");
7062
7063 H.restoreIndent();
7064 if(lambdaCustomOut)
7065 {
7066 //
7067 // "Custom" implementation in .cpp file
7068 //
7069
7070 C << sp;
7071 C << nl << "::std::function<void()>";
7072 C << nl << scoped << name << "Async(";
7073 C.useCurrentPosAsIndent();
7074 if(!inParamsImplDecl.empty())
7075 {
7076 for(vector<string>::const_iterator q = inParamsImplDecl.begin(); q != inParamsImplDecl.end(); ++q)
7077 {
7078 if(q != inParamsImplDecl.begin())
7079 {
7080 C << " ";
7081 }
7082 C << *q << ",";
7083 }
7084 C << nl;
7085 }
7086 C << "::std::function<void " << spar << lambdaOutParams << epar << "> response,";
7087 C << nl << "::std::function<void(::std::exception_ptr)> ex,";
7088 C << nl << "::std::function<void(bool)> sent,";
7089 C << nl << "const ::Ice::Context& context)";
7090 C.restoreIndent();
7091 C << sb;
7092 if(p->returnsData())
7093 {
7094 C << nl << "_checkTwowayOnly(" << flatName << ");";
7095 }
7096
7097 C << nl << "::std::function<void(::Ice::InputStream*)> read;";
7098 C << nl << "if(response)";
7099 C << sb;
7100 C << nl << "read = [response](::Ice::InputStream* istr)";
7101 C << sb;
7102 C << nl << "istr->startEncapsulation();";
7103 writeAllocateCode(C, outParams, p, true, clScope, _useWstring | TypeContextInParam | TypeContextCpp11);
7104 writeUnmarshalCode(C, outParams, p, true, _useWstring | TypeContextInParam | TypeContextCpp11);
7105
7106 if(p->returnsClasses(false))
7107 {
7108 C << nl << "istr->readPendingValues();";
7109 }
7110 C << nl << "istr->endEncapsulation();";
7111 C << nl << "try" << sb;
7112 C << nl << "response" << spar;
7113 if(ret)
7114 {
7115 C << "ret";
7116 }
7117 for(ParamDeclList::const_iterator q = outParams.begin(); q != outParams.end(); ++q)
7118 {
7119 C << fixKwd(paramPrefix + (*q)->name());
7120 }
7121 C << epar << ";";
7122 C << eb;
7123 C << nl << "catch(...)";
7124 C << sb;
7125 C << nl << "throw ::std::current_exception();";
7126 C << eb;
7127 C << eb << ";";
7128 C << eb;
7129 C << nl << "auto outAsync = ::std::make_shared<::IceInternal::CustomLambdaOutgoing>(";
7130 C << "shared_from_this(), read, ex, sent);";
7131 C << sp;
7132
7133 C << nl << "outAsync->invoke(" << flatName << ", ";
7134 C << operationModeToString(p->sendMode(), true) << ", " << opFormatTypeToString(p, true) << ", context,";
7135 C.inc();
7136 C << nl;
7137
7138 writeInParamsLambda(C, p, inParams, clScope);
7139 C << "," << nl;
7140 throwUserExceptionLambda(C, p->throws(), clScope);
7141
7142 C.dec();
7143 C << ");";
7144 C << nl << "return [outAsync]() { outAsync->cancel(); };";
7145 C << eb;
7146 }
7147 else
7148 {
7149 //
7150 // Simple implementation directly in header file
7151 //
7152
7153 H << sb;
7154 if(futureOutParams.size() > 1)
7155 {
7156 H << nl << "auto _responseCb = [response](" << futureT << "&& _result)";
7157 H << sb;
7158 H << nl << responseParam << spar;
7159
7160 if(ret)
7161 {
7162 H << condMove(isMovable(ret), string("_result.") + returnValueS);
7163 }
7164 for(ParamDeclList::const_iterator q = outParams.begin(); q != outParams.end(); ++q)
7165 {
7166 H << condMove(isMovable((*q)->type()), "_result." + fixKwd((*q)->name()));
7167 }
7168 H << epar << ";" << eb << ";";
7169 }
7170
7171 H << nl << "return _makeLamdaOutgoing<" << futureT << ">" << spar;
7172
7173 H << (futureOutParams.size() > 1 ? "_responseCb" : responseParam) << exParam << sentParam << "this";
7174 H << string("&" + getUnqualified(scoped, clScope.substr(2)) + "_iceI_" + name);
7175 for(ParamDeclList::const_iterator q = inParams.begin(); q != inParams.end(); ++q)
7176 {
7177 H << fixKwd((*q)->name());
7178 }
7179 H << contextParam << epar << ";";
7180 H << eb;
7181 }
7182
7183 //
7184 // Private implementation
7185 //
7186
7187 H << sp;
7188 H << nl << "/// \\cond INTERNAL";
7189 H << nl << _dllMemberExport << "void _iceI_" << name << spar;
7190 H << "const ::std::shared_ptr<::IceInternal::OutgoingAsyncT<" + futureT + ">>&";
7191 H << inParamsS;
7192 H << ("const " + getUnqualified("::Ice::Context&", clScope));
7193 H << epar << ";";
7194 H << nl << "/// \\endcond";
7195
7196 C << sp;
7197 C << nl << "/// \\cond INTERNAL";
7198 C << nl << "void" << nl << scoped << "_iceI_" << name << spar;
7199 C << "const ::std::shared_ptr<::IceInternal::OutgoingAsyncT<" + futureT + ">>& outAsync";
7200 C << inParamsImplDecl << ("const " + getUnqualified("::Ice::Context&", clScope) + " context");
7201 C << epar;
7202 C << sb;
7203 if(p->returnsData())
7204 {
7205 C << nl << "_checkTwowayOnly(" << flatName << ");";
7206 }
7207 C << nl << "outAsync->invoke(" << flatName << ", ";
7208 C << getUnqualified(operationModeToString(p->sendMode(), true), clScope) << ", "
7209 << getUnqualified(opFormatTypeToString(p, true), clScope) << ", context,";
7210 C.inc();
7211 C << nl;
7212
7213 writeInParamsLambda(C, p, inParams, clScope);
7214 C << "," << nl;
7215 throwUserExceptionLambda(C, p->throws(), clScope);
7216
7217 if(futureOutParams.size() > 1)
7218 {
7219 //
7220 // Generate a read method if there are more than one ret/out parameter. If there's
7221 // only one, we rely on the default read method from LambdaOutgoing
7222 // except if the unique ret/out is optional or is an array/range.
7223 //
7224 C << "," << nl << "[](" << getUnqualified("::Ice::InputStream*", clScope) << " istr)";
7225 C << sb;
7226 C << nl << futureT << " v;";
7227 writeUnmarshalCode(C, outParams, p, false, _useWstring | TypeContextCpp11, "", returnValueS, "v");
7228
7229 if(p->returnsClasses(false))
7230 {
7231 C << nl << "istr->readPendingValues();";
7232 }
7233 C << nl << "return v;";
7234 C << eb;
7235 }
7236 else if(outParamsHasOpt || p->returnsClasses(false))
7237 {
7238 //
7239 // If there's only one optional ret/out parameter, we still need to generate
7240 // a read method, we can't rely on the default read method which wouldn't
7241 // known which tag to use.
7242 //
7243 C << "," << nl << "[](" << getUnqualified("::Ice::InputStream*", clScope) << " istr)";
7244 C << sb;
7245
7246 writeAllocateCode(C, outParams, p, true, clScope, _useWstring | TypeContextCpp11);
7247 writeUnmarshalCode(C, outParams, p, true, _useWstring | TypeContextCpp11);
7248
7249 if(p->returnsClasses(false))
7250 {
7251 C << nl << "istr->readPendingValues();";
7252 }
7253
7254 if(ret)
7255 {
7256 C << nl << "return ret;";
7257 }
7258 else
7259 {
7260 C << nl << "return " << fixKwd(paramPrefix + outParams.front()->name()) << ";";
7261 }
7262 C << eb;
7263 }
7264
7265 C.dec();
7266 C << ");" << eb;
7267 C << nl << "/// \\endcond";
7268 }
7269
7270 void
visitEnum(const EnumPtr & p)7271 Slice::Gen::Cpp11TypesVisitor::visitEnum(const EnumPtr& p)
7272 {
7273 bool unscoped = findMetaData(p->getMetaData(), TypeContextCpp11) == "%unscoped";
7274 H << sp;
7275 writeDocSummary(H, p);
7276 H << nl << "enum ";
7277 if(!unscoped)
7278 {
7279 H << "class ";
7280 }
7281 H << fixKwd(p->name());
7282 if(!unscoped && p->maxValue() <= 0xFF)
7283 {
7284 H << " : unsigned char";
7285 }
7286 H << sb;
7287
7288 EnumeratorList enumerators = p->enumerators();
7289 //
7290 // Check if any of the enumerators were assigned an explicit value.
7291 //
7292 const bool explicitValue = p->explicitValue();
7293 for(EnumeratorList::const_iterator en = enumerators.begin(); en != enumerators.end();)
7294 {
7295 writeDocSummary(H, *en);
7296 H << nl << fixKwd((*en)->name());
7297 //
7298 // If any of the enumerators were assigned an explicit value, we emit
7299 // an explicit value for *all* enumerators.
7300 //
7301 if(explicitValue)
7302 {
7303 H << " = " << int64ToString((*en)->value());
7304 }
7305 if(++en != enumerators.end())
7306 {
7307 H << ',';
7308 }
7309 }
7310 H << eb << ';';
7311 }
7312
7313 void
visitConst(const ConstPtr & p)7314 Slice::Gen::Cpp11TypesVisitor::visitConst(const ConstPtr& p)
7315 {
7316 const string scope = fixKwd(p->scope());
7317 H << sp;
7318 writeDocSummary(H, p);
7319 H << nl << (isConstexprType(p->type()) ? "constexpr " : "const ")
7320 << typeToString(p->type(), scope, p->typeMetaData(), _useWstring | TypeContextCpp11) << " " << fixKwd(p->name())
7321 << " = ";
7322 writeConstantValue(H, p->type(), p->valueType(), p->value(), _useWstring | TypeContextCpp11, p->typeMetaData(),
7323 scope);
7324 H << ';';
7325 }
7326
7327 void
emitUpcall(const ExceptionPtr & base,const string & call,const string & scope,bool isLocal)7328 Slice::Gen::Cpp11TypesVisitor::emitUpcall(const ExceptionPtr& base, const string& call, const string& scope,
7329 bool isLocal)
7330 {
7331 C << nl;
7332 if(base)
7333 {
7334 C << getUnqualified(fixKwd(base->scoped()), scope);
7335 }
7336 else
7337 {
7338 getUnqualified(isLocal ? "::Ice::LocalException" : "::Ice::UserException", scope);
7339 }
7340 C << call;
7341 }
7342
Cpp11ObjectVisitor(::IceUtilInternal::Output & h,::IceUtilInternal::Output & c,const std::string & dllExport)7343 Slice::Gen::Cpp11ObjectVisitor::Cpp11ObjectVisitor(::IceUtilInternal::Output& h,
7344 ::IceUtilInternal::Output& c,
7345 const std::string& dllExport) :
7346 H(h),
7347 C(c),
7348 _dllExport(dllExport),
7349 _dllClassExport(toDllClassExport(dllExport)), _dllMemberExport(toDllMemberExport(dllExport)),
7350 _doneStaticSymbol(false),
7351 _useWstring(false)
7352 {
7353 }
7354
7355 void
emitDataMember(const DataMemberPtr & p)7356 Slice::Gen::Cpp11ObjectVisitor::emitDataMember(const DataMemberPtr& p)
7357 {
7358 string name = fixKwd(p->name());
7359 int typeContext = _useWstring | TypeContextCpp11;
7360 ContainerPtr container = p->container();
7361 ClassDefPtr cl = ClassDefPtr::dynamicCast(container);
7362 string scope = fixKwd(cl->scope());
7363 if(cl->isLocal())
7364 {
7365 typeContext |= TypeContextLocal;
7366 }
7367
7368 writeDocSummary(H, p);
7369 H << nl << typeToString(p->type(), p->optional(), scope, p->getMetaData(), typeContext) << ' ' << name;
7370
7371 string defaultValue = p->defaultValue();
7372 if(!defaultValue.empty())
7373 {
7374 BuiltinPtr builtin = BuiltinPtr::dynamicCast(p->type());
7375 if(p->optional() && builtin && builtin->kind() == Builtin::KindString)
7376 {
7377 //
7378 // = "<string literal>" doesn't work for optional<std::string>
7379 //
7380 H << '{';
7381 writeConstantValue(H, p->type(), p->defaultValueType(), defaultValue, _useWstring | TypeContextCpp11,
7382 p->getMetaData(), scope);
7383 H << '}';
7384 }
7385 else
7386 {
7387 H << " = ";
7388 writeConstantValue(H, p->type(), p->defaultValueType(), defaultValue, _useWstring | TypeContextCpp11,
7389 p->getMetaData(), scope);
7390 }
7391 }
7392 H << ";";
7393 }
7394
7395 void
emitUpcall(const ClassDefPtr & base,const string & call,const string & scope)7396 Slice::Gen::Cpp11InterfaceVisitor::emitUpcall(const ClassDefPtr& base, const string& call, const string& scope)
7397 {
7398 C << nl;
7399 if(base)
7400 {
7401 C << getUnqualified(fixKwd(base->scoped()), scope);
7402 }
7403 else
7404 {
7405 C << getUnqualified("::Ice::Object", scope);
7406 }
7407 C << call;
7408 }
7409
7410 void
emitUpcall(const ClassDefPtr & base,const string & call,const string & scope)7411 Slice::Gen::Cpp11ValueVisitor::emitUpcall(const ClassDefPtr& base, const string& call, const string& scope)
7412 {
7413 C << nl;
7414 if(base)
7415 {
7416 C << getUnqualified(fixKwd(base->scoped()), scope);
7417 }
7418 else
7419 {
7420 C << getUnqualified("::Ice::Value", scope);
7421 }
7422 C << call;
7423 }
7424
Cpp11LocalObjectVisitor(::IceUtilInternal::Output & h,::IceUtilInternal::Output & c,const std::string & dllExport)7425 Slice::Gen::Cpp11LocalObjectVisitor::Cpp11LocalObjectVisitor(::IceUtilInternal::Output& h,
7426 ::IceUtilInternal::Output& c,
7427 const std::string& dllExport) :
7428 Cpp11ObjectVisitor(h, c, dllExport)
7429 {
7430 }
7431
7432 bool
visitModuleStart(const ModulePtr & p)7433 Slice::Gen::Cpp11LocalObjectVisitor::visitModuleStart(const ModulePtr& p)
7434 {
7435 if(!p->hasLocalClassDefs())
7436 {
7437 return false;
7438 }
7439
7440 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
7441 string name = fixKwd(p->name());
7442 H << sp << nl << "namespace " << name << nl << '{';
7443 return true;
7444 }
7445
7446 void
visitModuleEnd(const ModulePtr &)7447 Slice::Gen::Cpp11LocalObjectVisitor::visitModuleEnd(const ModulePtr&)
7448 {
7449 H << sp;
7450 H << nl << '}';
7451 _useWstring = resetUseWstring(_useWstringHist);
7452 }
7453
7454 bool
visitClassDefStart(const ClassDefPtr & p)7455 Slice::Gen::Cpp11LocalObjectVisitor::visitClassDefStart(const ClassDefPtr& p)
7456 {
7457 if(!p->isLocal())
7458 {
7459 return false;
7460 }
7461
7462 string name = fixKwd(p->name());
7463 string scope = fixKwd(p->scope());
7464 if(p->isDelegate())
7465 {
7466 int typeCtx = _useWstring | TypeContextLocal | TypeContextCpp11;
7467
7468 // A delegate only has one operation
7469 OperationPtr op = p->allOperations().front();
7470
7471 // Generate alias
7472 H << sp;
7473 CommentPtr comment = op->parseComment(false);
7474 if(comment)
7475 {
7476 writeOpDocSummary(H, op, comment, OpDocAllParams, true, StringList(), StringList(), comment->returns());
7477 }
7478 H << nl << "using " << name << " = ";
7479
7480 TypePtr ret = op->returnType();
7481 string retS = returnTypeToString(ret, op->returnIsOptional(), scope, op->getMetaData(), typeCtx);
7482
7483 H << "::std::function<" << retS << "(";
7484
7485 ParamDeclList paramList = op->parameters();
7486 for(ParamDeclList::iterator q = paramList.begin(); q != paramList.end(); ++q)
7487 {
7488 if((*q)->isOutParam())
7489 {
7490 H << outputTypeToString((*q)->type(), (*q)->optional(), scope, (*q)->getMetaData(), typeCtx);
7491 }
7492 else
7493 {
7494 H << inputTypeToString((*q)->type(), (*q)->optional(), scope, (*q)->getMetaData(), typeCtx);
7495 }
7496 H << " " << fixKwd((*q)->name());
7497 H << (IceUtilInternal::distance(q, paramList.end()) == 1 ? "" : ", ");
7498 }
7499 H << ")>;";
7500
7501 return false;
7502 }
7503
7504 string scoped = fixKwd(p->scoped());
7505 ClassList bases = p->bases();
7506 ClassDefPtr base;
7507 if(!bases.empty() && !bases.front()->isInterface())
7508 {
7509 base = bases.front();
7510 }
7511 DataMemberList dataMembers = p->dataMembers();
7512 DataMemberList allDataMembers = p->allDataMembers();
7513
7514 H << sp;
7515 writeDocSummary(H, p);
7516 H << nl << "class " << _dllClassExport << name;
7517 H.useCurrentPosAsIndent();
7518 if(!bases.empty())
7519 {
7520 H << " : ";
7521 ClassList::const_iterator q = bases.begin();
7522 bool virtualInheritance = p->isInterface();
7523 while(q != bases.end())
7524 {
7525 H << "public ";
7526 if(virtualInheritance || (*q)->isInterface())
7527 {
7528 H << "virtual ";
7529 }
7530
7531 H << fixKwd((*q)->scoped());
7532 if(++q != bases.end())
7533 {
7534 H << ',' << nl;
7535 }
7536 }
7537 }
7538
7539 H.restoreIndent();
7540 H << sb;
7541 H.dec();
7542 H << nl << "public:" << sp;
7543 H.inc();
7544
7545 //
7546 // Out of line virtual dtor to avoid weak vtable
7547 //
7548 H << nl << _dllMemberExport << "virtual ~" << name << "();";
7549 C << sp << nl << scoped.substr(2) << "::~" << name << "()";
7550 C << sb;
7551 C << eb;
7552
7553 if(!p->isInterface())
7554 {
7555 if(p->hasDefaultValues())
7556 {
7557 H << sp << nl << name << "() :";
7558 H.inc();
7559 writeDataMemberInitializers(H, dataMembers, _useWstring | TypeContextCpp11 | TypeContextLocal);
7560 H.dec();
7561 H << sb;
7562 H << eb;
7563 }
7564 else
7565 {
7566 H << sp << nl << name << "() = default;";
7567 }
7568
7569 H << sp << nl << name << "(const " << name << "&) = default;";
7570 H << nl << name << "(" << name << "&&) = default;";
7571 H << nl << name << "& operator=(const " << name << "&) = default;";
7572 H << nl << name << "& operator=(" << name << "&&) = default;";
7573
7574 emitOneShotConstructor(p);
7575 }
7576
7577 if(p->hasMetaData("cpp:comparable"))
7578 {
7579 H << sp;
7580 H << nl << "virtual bool operator==(const " << p->name() << "&) const = 0;";
7581 H << nl << "virtual bool operator<(const " << p->name() << "&) const = 0;";
7582 }
7583 return true;
7584 }
7585
7586 void
visitClassDefEnd(const ClassDefPtr & p)7587 Slice::Gen::Cpp11LocalObjectVisitor::visitClassDefEnd(const ClassDefPtr& p)
7588 {
7589 string scoped = fixKwd(p->scoped());
7590 string scope = fixKwd(p->scope());
7591 ClassList bases = p->bases();
7592 ClassDefPtr base;
7593 if(!bases.empty() && !bases.front()->isInterface())
7594 {
7595 base = bases.front();
7596 }
7597
7598 //
7599 // Emit data members. Access visibility may be specified by metadata.
7600 //
7601 bool inProtected = false;
7602 DataMemberList dataMembers = p->dataMembers();
7603 bool prot = p->hasMetaData("protected");
7604 bool needSp = true;
7605 for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
7606 {
7607 if(prot || (*q)->hasMetaData("protected"))
7608 {
7609 if(!inProtected)
7610 {
7611 H.dec();
7612 H << sp << nl << "protected:" << sp;
7613 H.inc();
7614 inProtected = true;
7615 needSp = false;
7616 }
7617 }
7618 else
7619 {
7620 if(inProtected)
7621 {
7622 H.dec();
7623 H << sp << nl << "public:" << sp;
7624 H.inc();
7625 inProtected = false;
7626 needSp = false;
7627 }
7628 }
7629
7630 if(needSp)
7631 {
7632 H << sp;
7633 needSp = false;
7634 }
7635
7636 emitDataMember(*q);
7637 }
7638
7639 H << eb << ';';
7640 }
7641
7642 bool
visitExceptionStart(const ExceptionPtr &)7643 Slice::Gen::Cpp11LocalObjectVisitor::visitExceptionStart(const ExceptionPtr&)
7644 {
7645 return false;
7646 }
7647
7648 bool
visitStructStart(const StructPtr &)7649 Slice::Gen::Cpp11LocalObjectVisitor::visitStructStart(const StructPtr&)
7650 {
7651 return false;
7652 }
7653
7654 void
visitOperation(const OperationPtr & p)7655 Slice::Gen::Cpp11LocalObjectVisitor::visitOperation(const OperationPtr& p)
7656 {
7657 string name = p->name();
7658 string scoped = fixKwd(p->scoped());
7659 string scope = fixKwd(p->scope());
7660
7661 int typeCtx = _useWstring | TypeContextLocal | TypeContextCpp11;
7662 TypePtr ret = p->returnType();
7663 string retS = returnTypeToString(ret, p->returnIsOptional(), scope, p->getMetaData(), typeCtx);
7664
7665 string params = "(";
7666
7667 ContainerPtr container = p->container();
7668 ClassDefPtr cl = ClassDefPtr::dynamicCast(container);
7669 string classScope = fixKwd(cl->scope());
7670
7671 string isConst = ((p->mode() == Operation::Nonmutating) || p->hasMetaData("cpp:const")) ? " const" : "";
7672 string noExcept = p->hasMetaData("cpp:noexcept") ? " noexcept" : "";
7673
7674 string deprecateSymbol = getDeprecateSymbol(p, cl);
7675
7676 CommentPtr comment = p->parseComment(false);
7677
7678 if(cl->hasMetaData("async-oneway") || p->hasMetaData("async-oneway"))
7679 {
7680 vector<string> paramsDeclAMI;
7681 vector<string> outParamsDeclAMI;
7682 vector<string> paramsArgAMI;
7683 ParamDeclList paramList = p->inParameters();
7684 for(ParamDeclList::const_iterator r = paramList.begin(); r != paramList.end(); ++r)
7685 {
7686 string paramName = fixKwd((*r)->name());
7687
7688 StringList metaData = (*r)->getMetaData();
7689 string typeString = inputTypeToString((*r)->type(), (*r)->optional(), classScope, metaData, typeCtx);
7690 paramsDeclAMI.push_back(typeString + ' ' + paramName);
7691 paramsArgAMI.push_back(paramName);
7692 }
7693
7694 H << sp;
7695 if(comment)
7696 {
7697 writeOpDocSummary(H, p, comment, OpDocAllParams, true, StringList(), StringList(), comment->returns());
7698 }
7699 H << nl << deprecateSymbol << "virtual " << retS << ' ' << fixKwd(name) << spar << paramsDeclAMI << epar
7700 << isConst << noExcept;
7701 H << sb;
7702 H << nl << name << "Async" << spar << paramsArgAMI << epar << ".get();";
7703 H << eb;
7704
7705 H << sp;
7706 if(comment)
7707 {
7708 string exParam = escapeParam(paramList, "exception");
7709 string sentParam = escapeParam(paramList, "sent");
7710 StringList postParams, returns;
7711 postParams.push_back("@param " + exParam + " The exception callback.");
7712 postParams.push_back("@param " + sentParam + " The sent callback.");
7713 returns.push_back("A function that can be called to cancel the invocation locally.");
7714 writeOpDocSummary(H, p, comment, OpDocInParams, false, StringList(), postParams, returns);
7715 }
7716 H << nl << "virtual ::std::function<void()>";
7717 H << nl << name << "Async(";
7718 H.useCurrentPosAsIndent();
7719 for(vector<string>::const_iterator i = paramsDeclAMI.begin(); i != paramsDeclAMI.end(); ++i)
7720 {
7721 if(i != paramsDeclAMI.begin())
7722 {
7723 H << nl;
7724 }
7725 H << *i << ",";
7726 }
7727 if(!paramsDeclAMI.empty())
7728 {
7729 H << nl;
7730 }
7731 H << "::std::function<void(::std::exception_ptr)> exception,";
7732 H << nl << "::std::function<void(bool)> sent = nullptr) = 0;";
7733 H.restoreIndent();
7734
7735 H << sp;
7736 if(comment)
7737 {
7738 StringList returns;
7739 returns.push_back("The future object for the invocation.");
7740 writeOpDocSummary(H, p, comment, OpDocInParams, false, StringList(), StringList(), returns);
7741 }
7742 H << nl << "template<template<typename> class P = ::std::promise>";
7743 H << nl << deprecateSymbol << "auto " << name << "Async" << spar << paramsDeclAMI << epar;
7744 H.inc();
7745 H << nl << "-> decltype(::std::declval<P<void>>().get_future())";
7746 H.dec();
7747 H << sb;
7748 H << nl << "using Promise = P<void>;";
7749 H << nl << "auto promise = ::std::make_shared<Promise>();";
7750
7751 H << nl << name << "Async(";
7752 H.useCurrentPosAsIndent();
7753 for(vector<string>::const_iterator i = paramsArgAMI.begin(); i != paramsArgAMI.end(); ++i)
7754 {
7755 if(i != paramsArgAMI.begin())
7756 {
7757 H << " ";
7758 }
7759 H << *i << ",";
7760 }
7761 if(!paramsArgAMI.empty())
7762 {
7763 H << nl;
7764 }
7765 H << "[promise](::std::exception_ptr ex)";
7766 H << sb;
7767 H << nl << "promise->set_exception(::std::move(ex));";
7768 H << eb << ",";
7769 H << nl << "[promise](bool)";
7770 H << sb;
7771 H << nl << "promise->set_value();";
7772 H << eb << ");";
7773 H.restoreIndent();
7774
7775 H << nl << "return promise->get_future();";
7776 H << eb;
7777 }
7778 else
7779 {
7780 ParamDeclList paramList = p->parameters();
7781 for(ParamDeclList::iterator q = paramList.begin(); q != paramList.end(); ++q)
7782 {
7783 string paramName = fixKwd((*q)->name());
7784 TypePtr type = (*q)->type();
7785 string typeString;
7786 if((*q)->isOutParam())
7787 {
7788 typeString = outputTypeToString(type, (*q)->optional(), classScope, (*q)->getMetaData(), typeCtx);
7789 }
7790 else
7791 {
7792 typeString = inputTypeToString(type, (*q)->optional(), classScope, (*q)->getMetaData(), typeCtx);
7793 }
7794
7795 if(q != paramList.begin())
7796 {
7797 params += ", ";
7798 }
7799
7800 params += typeString;
7801 params += ' ';
7802 params += paramName;
7803 }
7804
7805 params += ')';
7806
7807 H << sp;
7808 if(comment)
7809 {
7810 writeOpDocSummary(H, p, comment, OpDocAllParams, true, StringList(), StringList(), comment->returns());
7811 }
7812 H << nl << deprecateSymbol << "virtual " << retS << ' ' << fixKwd(name) << params << isConst << noExcept
7813 << " = 0;";
7814 }
7815 }
7816
Cpp11InterfaceVisitor(::IceUtilInternal::Output & h,::IceUtilInternal::Output & c,const std::string & dllExport)7817 Slice::Gen::Cpp11InterfaceVisitor::Cpp11InterfaceVisitor(::IceUtilInternal::Output& h,
7818 ::IceUtilInternal::Output& c,
7819 const std::string& dllExport) :
7820 Cpp11ObjectVisitor(h, c, dllExport)
7821 {
7822 }
7823
7824 bool
visitModuleStart(const ModulePtr & p)7825 Slice::Gen::Cpp11InterfaceVisitor::visitModuleStart(const ModulePtr& p)
7826 {
7827 if(!p->hasNonLocalInterfaceDefs())
7828 {
7829 return false;
7830 }
7831
7832 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
7833 string name = fixKwd(p->name());
7834 H << sp << nl << "namespace " << name << nl << '{';
7835 return true;
7836 }
7837
7838 void
visitModuleEnd(const ModulePtr &)7839 Slice::Gen::Cpp11InterfaceVisitor::visitModuleEnd(const ModulePtr&)
7840 {
7841 H << sp;
7842 H << nl << '}';
7843
7844 _useWstring = resetUseWstring(_useWstringHist);
7845 }
7846
7847 bool
visitClassDefStart(const ClassDefPtr & p)7848 Slice::Gen::Cpp11InterfaceVisitor::visitClassDefStart(const ClassDefPtr& p)
7849 {
7850 if(p->isLocal() || (!p->isInterface() && p->allOperations().empty()))
7851 {
7852 return false;
7853 }
7854
7855 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
7856
7857 string suffix = p->isInterface() ? "" : "Disp";
7858
7859 string name = fixKwd(p->name() + suffix);
7860 string scope = fixKwd(p->scope());
7861 string scoped = fixKwd(p->scope() + p->name() + suffix);
7862 ClassList bases = p->bases();
7863 ClassDefPtr base;
7864 if(!bases.empty() && !bases.front()->isInterface())
7865 {
7866 base = bases.front();
7867 }
7868
7869 H << sp;
7870 writeDocSummary(H, p);
7871 H << nl << "class " << _dllExport << name << " : ";
7872 H.useCurrentPosAsIndent();
7873 if(bases.empty() || (base && base->allOperations().empty()))
7874 {
7875 H << "public virtual " << getUnqualified("::Ice::Object", scope);
7876 }
7877 else
7878 {
7879 ClassList::const_iterator q = bases.begin();
7880 while(q != bases.end())
7881 {
7882 string baseSuffix = (*q)->isInterface() ? "" : "Disp";
7883 string baseScoped = fixKwd((*q)->scope() + (*q)->name() + baseSuffix);
7884
7885 H << "public virtual " << getUnqualified(baseScoped, scope);
7886 if(++q != bases.end())
7887 {
7888 H << ',' << nl;
7889 }
7890 }
7891 }
7892
7893 H.restoreIndent();
7894 H << sb;
7895 H.dec();
7896 H << nl << "public:" << sp;
7897 H.inc();
7898
7899 //
7900 // In C++, a nested type cannot have the same name as the enclosing type
7901 //
7902 if(name != "ProxyType")
7903 {
7904 H << nl << "using ProxyType = " << p->name() << "Prx;";
7905 }
7906
7907 vector<string> params;
7908 vector<string> allTypes;
7909 vector<string> allParamDecls;
7910
7911 ClassList allBases = p->allBases();
7912 StringList ids;
7913 transform(allBases.begin(), allBases.end(), back_inserter(ids), ::IceUtil::constMemFun(&Contained::scoped));
7914 StringList other;
7915 other.push_back(p->scoped());
7916 other.push_back("::Ice::Object");
7917 other.sort();
7918 ids.merge(other);
7919 ids.unique();
7920 StringList::const_iterator scopedIter = find(ids.begin(), ids.end(), p->scoped());
7921 assert(scopedIter != ids.end());
7922
7923 H << sp;
7924 H << nl << "/**";
7925 H << nl << " * Determines whether this object supports an interface with the given Slice type ID.";
7926 H << nl << " * @param id The fully-scoped Slice type ID.";
7927 H << nl << " * @param current The Current object for the invocation.";
7928 H << nl << " * @return True if this object supports the interface, false, otherwise.";
7929 H << nl << " */";
7930 H << nl << "virtual bool ice_isA(::std::string id, const " << getUnqualified("::Ice::Current&", scope)
7931 << " current) const override;";
7932 H << sp;
7933 H << nl << "/**";
7934 H << nl << " * Obtains a list of the Slice type IDs representing the interfaces supported by this object.";
7935 H << nl << " * @param current The Current object for the invocation.";
7936 H << nl << " * @return A list of fully-scoped type IDs.";
7937 H << nl << " */";
7938 H << nl
7939 << "virtual ::std::vector<::std::string> ice_ids(const " << getUnqualified("::Ice::Current&", scope)
7940 << " current) const override;";
7941 H << sp;
7942 H << nl << "/**";
7943 H << nl << " * Obtains a Slice type ID representing the most-derived interface supported by this object.";
7944 H << nl << " * @param current The Current object for the invocation.";
7945 H << nl << " * @return A fully-scoped type ID.";
7946 H << nl << " */";
7947 H << nl << "virtual ::std::string ice_id(const " << getUnqualified("::Ice::Current&", scope)
7948 << " current) const override;";
7949 H << sp;
7950 H << nl << "/**";
7951 H << nl << " * Obtains the Slice type ID corresponding to this class.";
7952 H << nl << " * @return A fully-scoped type ID.";
7953 H << nl << " */";
7954 H << nl << "static const ::std::string& ice_staticId();";
7955
7956 string flatName = "iceC" + p->flattenedScope() + p->name() + "_ids";
7957
7958 C << sp;
7959 C << nl << "bool" << nl << scoped.substr(2) << "::ice_isA(::std::string s, const "
7960 << getUnqualified("::Ice::Current&", scope) << ") const";
7961 C << sb;
7962 C << nl << "return ::std::binary_search(" << flatName << ", " << flatName << " + " << ids.size() << ", s);";
7963 C << eb;
7964
7965 C << sp;
7966 C << nl << "::std::vector<::std::string>" << nl << scoped.substr(2) << "::ice_ids(const "
7967 << getUnqualified("::Ice::Current&", scope) << ") const";
7968 C << sb;
7969 C << nl << "return ::std::vector<::std::string>(&" << flatName << "[0], &" << flatName << '[' << ids.size()
7970 << "]);";
7971 C << eb;
7972
7973 C << sp;
7974 C << nl << "::std::string" << nl << scoped.substr(2) << "::ice_id(const " << getUnqualified("::Ice::Current&", scope)
7975 << ") const";
7976 C << sb;
7977 C << nl << "return ice_staticId();";
7978 C << eb;
7979
7980 C << sp;
7981 C << nl << "const ::std::string&" << nl << scoped.substr(2) << "::ice_staticId()";
7982 C << sb;
7983 //
7984 // Use local static so that ice_staticId() is usable during static construction.
7985 //
7986 C << nl << "static const ::std::string typeId = \"" << *scopedIter << "\";";
7987 C << nl << "return typeId;";
7988 C << eb;
7989 return true;
7990 }
7991
7992 void
visitClassDefEnd(const ClassDefPtr & p)7993 Slice::Gen::Cpp11InterfaceVisitor::visitClassDefEnd(const ClassDefPtr& p)
7994 {
7995 string suffix = p->isInterface() ? "" : "Disp";
7996 string scoped = fixKwd(p->scope() + p->name() + suffix);
7997
7998 string scope = fixKwd(p->scope());
7999 string name = fixKwd(p->name() + suffix);
8000 ClassList bases = p->bases();
8001 ClassDefPtr base;
8002 if(!bases.empty() && !bases.front()->isInterface())
8003 {
8004 base = bases.front();
8005 }
8006
8007 OperationList allOps = p->allOperations();
8008 if(!allOps.empty())
8009 {
8010 StringList allOpNames;
8011 transform(allOps.begin(), allOps.end(), back_inserter(allOpNames), ::IceUtil::constMemFun(&Contained::name));
8012 allOpNames.push_back("ice_id");
8013 allOpNames.push_back("ice_ids");
8014 allOpNames.push_back("ice_isA");
8015 allOpNames.push_back("ice_ping");
8016 allOpNames.sort();
8017 allOpNames.unique();
8018
8019 string flatName = "iceC" + p->flattenedScope() + p->name() + "_ops";
8020
8021 H << sp;
8022 H << nl << "/// \\cond INTERNAL";
8023 H << nl << "virtual bool _iceDispatch(::IceInternal::Incoming&, const "
8024 << getUnqualified("::Ice::Current&", scope) << ") override;";
8025 H << nl << "/// \\endcond";
8026
8027 C << sp;
8028 C << nl << "/// \\cond INTERNAL";
8029 C << nl << "bool";
8030 C << nl << scoped.substr(2) << "::_iceDispatch(::IceInternal::Incoming& in, const "
8031 << getUnqualified("::Ice::Current&", scope) << " current)";
8032 C << sb;
8033
8034 C << nl << "::std::pair<const ::std::string*, const ::std::string*> r = "
8035 << "::std::equal_range(" << flatName << ", " << flatName << " + " << allOpNames.size()
8036 << ", current.operation);";
8037 C << nl << "if(r.first == r.second)";
8038 C << sb;
8039 C << nl << "throw " << getUnqualified("::Ice::OperationNotExistException", scope)
8040 << "(__FILE__, __LINE__, current.id, current.facet, current.operation);";
8041 C << eb;
8042 C << sp;
8043 C << nl << "switch(r.first - " << flatName << ')';
8044 C << sb;
8045 int i = 0;
8046 for(StringList::const_iterator q = allOpNames.begin(); q != allOpNames.end(); ++q)
8047 {
8048 C << nl << "case " << i++ << ':';
8049 C << sb;
8050 C << nl << "return _iceD_" << *q << "(in, current);";
8051 C << eb;
8052 }
8053 C << nl << "default:";
8054 C << sb;
8055 C << nl << "assert(false);";
8056 C << nl << "throw " << getUnqualified("::Ice::OperationNotExistException", scope)
8057 << "(__FILE__, __LINE__, current.id, current.facet, current.operation);";
8058 C << eb;
8059 C << eb;
8060 C << eb;
8061 C << nl << "/// \\endcond";
8062 }
8063
8064 H << eb << ';';
8065
8066 _useWstring = resetUseWstring(_useWstringHist);
8067 }
8068
8069 bool
visitExceptionStart(const ExceptionPtr &)8070 Slice::Gen::Cpp11InterfaceVisitor::visitExceptionStart(const ExceptionPtr&)
8071 {
8072 return false;
8073 }
8074
8075 bool
visitStructStart(const StructPtr &)8076 Slice::Gen::Cpp11InterfaceVisitor::visitStructStart(const StructPtr&)
8077 {
8078 return false;
8079 }
8080
8081 void
visitOperation(const OperationPtr & p)8082 Slice::Gen::Cpp11InterfaceVisitor::visitOperation(const OperationPtr& p)
8083 {
8084 string name = p->name();
8085
8086 TypePtr ret = p->returnType();
8087
8088 vector<string> params;
8089 vector<string> args;
8090
8091 vector<string> responseParams;
8092 vector<string> responseParamsDecl;
8093 vector<string> responseParamsImplDecl;
8094
8095 ContainerPtr container = p->container();
8096 ClassDefPtr cl = ClassDefPtr::dynamicCast(container);
8097 string classScope = fixKwd(cl->scope());
8098
8099 string suffix = cl->isInterface() ? "" : "Disp";
8100 string scope = fixKwd(cl->scope() + cl->name() + suffix + "::");
8101 string scoped = fixKwd(cl->scope() + cl->name() + suffix + "::" + p->name());
8102
8103 ParamDeclList inParams = p->inParameters();
8104 ParamDeclList outParams = p->outParameters();
8105 ParamDeclList paramList = p->parameters();
8106
8107 const bool amd = (cl->hasMetaData("amd") || p->hasMetaData("amd"));
8108
8109 const string returnValueParam = escapeParam(outParams, "returnValue");
8110 const string responsecbParam = escapeParam(inParams, "response");
8111 const string excbParam = escapeParam(inParams, "exception");
8112 const string currentParam = escapeParam(amd ? inParams : paramList, "current");
8113 const string currentTypeDecl = "const " + getUnqualified("::Ice::Current&", classScope);
8114 const string currentDecl = currentTypeDecl + " " + currentParam;
8115
8116 CommentPtr comment = p->parseComment(false);
8117
8118 if(ret)
8119 {
8120 string typeS = inputTypeToString(ret, p->returnIsOptional(), classScope, p->getMetaData(),
8121 _useWstring | TypeContextCpp11);
8122 responseParams.push_back(typeS + " " + returnValueParam);
8123 responseParamsDecl.push_back(typeS + " ret");
8124 responseParamsImplDecl.push_back(typeS + " ret");
8125 }
8126
8127 string retS;
8128 if(amd)
8129 {
8130 retS = "void";
8131 }
8132 else if(p->hasMarshaledResult())
8133 {
8134 retS = resultStructName(name, "", true);
8135 }
8136 else
8137 {
8138 retS = returnTypeToString(ret, p->returnIsOptional(), classScope, p->getMetaData(),
8139 _useWstring | TypeContextCpp11);
8140 }
8141
8142 for(ParamDeclList::iterator q = paramList.begin(); q != paramList.end(); ++q)
8143 {
8144 TypePtr type = (*q)->type();
8145 string paramName = fixKwd((*q)->name());
8146 bool isOutParam = (*q)->isOutParam();
8147 string typeString;
8148 int typeCtx = _useWstring | TypeContextCpp11;
8149
8150 if(!isOutParam)
8151 {
8152 params.push_back(typeToString(type, (*q)->optional(), classScope, (*q)->getMetaData(),
8153 typeCtx | TypeContextInParam) + " " + paramName);
8154 args.push_back(condMove(isMovable(type) && !isOutParam, paramPrefix + (*q)->name()));
8155 }
8156 else
8157 {
8158 if(!p->hasMarshaledResult() && !amd)
8159 {
8160 params.push_back(
8161 outputTypeToString(type, (*q)->optional(), classScope, (*q)->getMetaData(), typeCtx) + " " +
8162 paramName);
8163 args.push_back(condMove(isMovable(type) && !isOutParam, paramPrefix + (*q)->name()));
8164 }
8165
8166 string responseTypeS = inputTypeToString((*q)->type(), (*q)->optional(), classScope, (*q)->getMetaData(),
8167 typeCtx);
8168 responseParams.push_back(responseTypeS + " " + paramName);
8169 responseParamsDecl.push_back(responseTypeS + " " + paramPrefix + (*q)->name());
8170 responseParamsImplDecl.push_back(responseTypeS + " " + paramPrefix + (*q)->name());
8171 }
8172 }
8173 if(amd)
8174 {
8175 if(p->hasMarshaledResult())
8176 {
8177 string resultName = resultStructName(name, "", true);
8178 params.push_back("::std::function<void(const " + resultName + "&)> " + responsecbParam);
8179 args.push_back("inA->response<" + resultName + ">()");
8180 }
8181 else
8182 {
8183 params.push_back("::std::function<void(" + joinString(responseParams, ", ") + ")> " + responsecbParam);
8184 args.push_back(ret || !outParams.empty() ? "responseCB" : "inA->response()");
8185 }
8186 params.push_back("::std::function<void(::std::exception_ptr)> " + excbParam);
8187 args.push_back("inA->exception()");
8188 }
8189 params.push_back(currentDecl);
8190 args.push_back("current");
8191
8192 if(cl->isInterface())
8193 {
8194 emitOpNameResult(H, p, _useWstring);
8195 }
8196
8197 if(p->hasMarshaledResult())
8198 {
8199 string resultName = resultStructName(name, "", true);
8200 H << sp;
8201 H << nl << "/**";
8202 H << nl << " * Marshaled result structure for operation " << (amd ? name + "Async" : fixKwd(name)) << ".";
8203 H << nl << " */";
8204 H << nl << "class " << resultName << " : public " << getUnqualified("::Ice::MarshaledResult", classScope);
8205 H << sb;
8206 H.dec();
8207 H << nl << "public:";
8208 H.inc();
8209 H << nl << "/**";
8210 H << nl << " * Marshals the results immediately.";
8211 if(ret && comment && !comment->returns().empty())
8212 {
8213 H << nl << " * @param " << returnValueParam << " " << getDocSentence(comment->returns());
8214 }
8215 map<string, StringList> paramComments;
8216 if(comment)
8217 {
8218 paramComments = comment->parameters();
8219 }
8220 const string mrcurrent = escapeParam(outParams, "current");
8221 for(ParamDeclList::iterator q = outParams.begin(); q != outParams.end(); ++q)
8222 {
8223 map<string, StringList>::iterator r = paramComments.find((*q)->name());
8224 if(r != paramComments.end())
8225 {
8226 H << nl << " * @param " << fixKwd(r->first) << " " << getDocSentence(r->second);
8227 }
8228 }
8229 H << nl << " * @param " << mrcurrent << " The Current object for the invocation.";
8230 H << nl << " */";
8231 H << nl << resultName << spar << responseParams << currentTypeDecl + " " + mrcurrent << epar << ";";
8232 H << eb << ';';
8233
8234 C << sp << nl << scope.substr(2) << resultName << "::" << resultName;
8235 C << spar << responseParamsImplDecl << currentTypeDecl + " current" << epar << ":";
8236 C.inc();
8237 C << nl << "MarshaledResult(current)";
8238 C.dec();
8239 C << sb;
8240 C << nl << "ostr->startEncapsulation(current.encoding, " << opFormatTypeToString(p, true) << ");";
8241 writeMarshalCode(C, outParams, p, true, TypeContextCpp11, "ostr");
8242 if(p->returnsClasses(false))
8243 {
8244 C << nl << "ostr->writePendingValues();";
8245 }
8246 C << nl << "ostr->endEncapsulation();";
8247 C << eb;
8248 }
8249
8250 string isConst = ((p->mode() == Operation::Nonmutating) || p->hasMetaData("cpp:const")) ? " const" : "";
8251
8252 string opName = amd ? (name + "Async") : fixKwd(name);
8253 string deprecateSymbol = getDeprecateSymbol(p, cl);
8254
8255 H << sp;
8256 if(comment)
8257 {
8258 OpDocParamType pt = (amd || p->hasMarshaledResult()) ? OpDocInParams : OpDocAllParams;
8259 StringList postParams, returns;
8260 if(amd)
8261 {
8262 postParams.push_back("@param " + responsecbParam + " The response callback.");
8263 postParams.push_back("@param " + excbParam + " The exception callback.");
8264 }
8265 else if(p->hasMarshaledResult())
8266 {
8267 returns.push_back("The marshaled result structure.");
8268 }
8269 else if(!amd)
8270 {
8271 returns = comment->returns();
8272 }
8273 postParams.push_back("@param " + currentParam + " The Current object for the invocation.");
8274 writeOpDocSummary(H, p, comment, pt, true, StringList(), postParams, returns);
8275 }
8276 H << nl << deprecateSymbol << "virtual " << retS << ' ' << opName << spar << params << epar << isConst << " = 0;";
8277 H << nl << "/// \\cond INTERNAL";
8278 H << nl << "bool _iceD_" << name << "(::IceInternal::Incoming&, const "
8279 << getUnqualified("::Ice::Current&", classScope) << ")" << isConst << ';';
8280 H << nl << "/// \\endcond";
8281
8282 C << sp;
8283 C << nl << "/// \\cond INTERNAL";
8284 C << nl << "bool";
8285 C << nl << scope.substr(2);
8286 C << "_iceD_" << name << "(::IceInternal::Incoming& inS, const "
8287 << getUnqualified("::Ice::Current&", classScope) << " current)" << isConst;
8288 C << sb;
8289 C << nl << "_iceCheckMode(" << getUnqualified(operationModeToString(p->mode(), true), classScope)
8290 << ", current.mode);";
8291
8292 if(!inParams.empty())
8293 {
8294 C << nl << "auto istr = inS.startReadParams();";
8295 writeAllocateCode(C, inParams, 0, true, classScope, _useWstring | TypeContextInParam | TypeContextCpp11);
8296 writeUnmarshalCode(C, inParams, 0, true, _useWstring | TypeContextInParam | TypeContextCpp11);
8297 if(p->sendsClasses(false))
8298 {
8299 C << nl << "istr->readPendingValues();";
8300 }
8301 C << nl << "inS.endReadParams();";
8302 }
8303 else
8304 {
8305 C << nl << "inS.readEmptyParams();";
8306 }
8307 if(p->format() != DefaultFormat)
8308 {
8309 C << nl << "inS.setFormat(" << opFormatTypeToString(p, true) << ");";
8310 }
8311
8312 if(!amd)
8313 {
8314 if(p->hasMarshaledResult())
8315 {
8316 C << nl << "inS.setMarshaledResult(";
8317 }
8318 else
8319 {
8320 writeAllocateCode(C, outParams, 0, true, classScope, _useWstring | TypeContextCpp11);
8321 if(ret)
8322 {
8323 C << nl << retS << " ret = ";
8324 }
8325 else
8326 {
8327 C << nl;
8328 }
8329 }
8330
8331 C << "this->" << opName << spar << args << epar;
8332 if(p->hasMarshaledResult())
8333 {
8334 C << ");";
8335 }
8336 else
8337 {
8338 C << ";";
8339 if(ret || !outParams.empty())
8340 {
8341 C << nl << "auto ostr = inS.startWriteParams();";
8342 writeMarshalCode(C, outParams, p, true, TypeContextCpp11);
8343 if(p->returnsClasses(false))
8344 {
8345 C << nl << "ostr->writePendingValues();";
8346 }
8347 C << nl << "inS.endWriteParams();";
8348 }
8349 else
8350 {
8351 C << nl << "inS.writeEmptyParams();";
8352 }
8353 }
8354 C << nl << "return true;";
8355 }
8356 else
8357 {
8358 C << nl << "auto inA = ::IceInternal::IncomingAsync::create(inS);";
8359 if(!p->hasMarshaledResult() && (ret || !outParams.empty()))
8360 {
8361 C << nl << "auto responseCB = [inA]" << spar << responseParamsDecl << epar;
8362 C << sb;
8363 C << nl << "auto ostr = inA->startWriteParams();";
8364 writeMarshalCode(C, outParams, p, true, TypeContextCpp11);
8365 if(p->returnsClasses(false))
8366 {
8367 C << nl << "ostr->writePendingValues();";
8368 }
8369 C << nl << "inA->endWriteParams();";
8370 C << nl << "inA->completed();";
8371 C << eb << ';';
8372 }
8373 C << nl << "this->" << opName << spar << args << epar << ';';
8374 C << nl << "return false;";
8375 }
8376 C << eb;
8377 C << nl << "/// \\endcond";
8378 }
8379
Cpp11ValueVisitor(::IceUtilInternal::Output & h,::IceUtilInternal::Output & c,const std::string & dllExport)8380 Slice::Gen::Cpp11ValueVisitor::Cpp11ValueVisitor(::IceUtilInternal::Output& h,
8381 ::IceUtilInternal::Output& c,
8382 const std::string& dllExport) :
8383 Cpp11ObjectVisitor(h, c, dllExport)
8384 {
8385 }
8386
8387 bool
visitModuleStart(const ModulePtr & p)8388 Slice::Gen::Cpp11ValueVisitor::visitModuleStart(const ModulePtr& p)
8389 {
8390 if(!p->hasValueDefs())
8391 {
8392 return false;
8393 }
8394
8395 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
8396 string name = fixKwd(p->name());
8397 H << sp << nl << "namespace " << name << nl << '{';
8398 return true;
8399 }
8400
8401 void
visitModuleEnd(const ModulePtr &)8402 Slice::Gen::Cpp11ValueVisitor::visitModuleEnd(const ModulePtr&)
8403 {
8404 H << sp;
8405 H << nl << '}';
8406
8407 _useWstring = resetUseWstring(_useWstringHist);
8408 }
8409
8410 bool
visitClassDefStart(const ClassDefPtr & p)8411 Slice::Gen::Cpp11ValueVisitor::visitClassDefStart(const ClassDefPtr& p)
8412 {
8413 if(p->isLocal() || p->isInterface())
8414 {
8415 return false;
8416 }
8417 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
8418
8419 string name = fixKwd(p->name());
8420 string scope = fixKwd(p->scope());
8421 string scoped = fixKwd(p->scoped());
8422 ClassList bases = p->bases();
8423 ClassDefPtr base;
8424 if(!bases.empty())
8425 {
8426 base = bases.front();
8427 }
8428 DataMemberList dataMembers = p->dataMembers();
8429 DataMemberList allDataMembers = p->allDataMembers();
8430
8431 H << sp;
8432 writeDocSummary(H, p);
8433 H << nl << "class " << _dllClassExport << name << " : public " << getUnqualified("::Ice::ValueHelper", scope)
8434 << "<" << name << ", ";
8435
8436 if(!base || (base && base->isInterface()))
8437 {
8438 H << getUnqualified("::Ice::Value", scope);
8439 }
8440 else
8441 {
8442 H << getUnqualified(fixKwd(base->scoped()), scope);
8443 }
8444 H << ">";
8445 H << sb;
8446 H.dec();
8447 H << nl << "public:" << sp;
8448 H.inc();
8449
8450 // Out of line dtor to avoid weak vtable
8451 H << nl << _dllMemberExport << "virtual ~" << name << "();";
8452 C << sp;
8453 C << nl << scoped.substr(2) << "::~" << name << "()";
8454 C << sb;
8455 C << eb;
8456
8457 vector<string> params;
8458
8459 for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
8460 {
8461 params.push_back(fixKwd((*q)->name()));
8462 }
8463
8464 H << sp << nl << name << "() = default;";
8465
8466 H << sp << nl << name << "(const " << name << "&) = default;";
8467 H << nl << name << "(" << name << "&&) = default;";
8468 H << nl << name << "& operator=(const " << name << "&) = default;";
8469 H << nl << name << "& operator=(" << name << "&&) = default;";
8470
8471 emitOneShotConstructor(p);
8472
8473 H << sp;
8474 H << nl << "/**";
8475 H << nl << " * Obtains a tuple containing all of the value's data members.";
8476 H << nl << " * @return The data members in a tuple.";
8477 H << nl << " */";
8478 writeIceTuple(H, fixKwd(p->scope()), p->allDataMembers(), _useWstring);
8479
8480 H << sp;
8481 H << nl << "/**";
8482 H << nl << " * Obtains the Slice type ID of this value.";
8483 H << nl << " * @return The fully-scoped type ID.";
8484 H << nl << " */";
8485 H << nl << _dllMemberExport << "static const ::std::string& ice_staticId();";
8486 return true;
8487 }
8488
8489 void
visitClassDefEnd(const ClassDefPtr & p)8490 Slice::Gen::Cpp11ValueVisitor::visitClassDefEnd(const ClassDefPtr& p)
8491 {
8492 string scoped = fixKwd(p->scoped());
8493 string scope = fixKwd(p->scope());
8494 string name = fixKwd(p->name());
8495 ClassList bases = p->bases();
8496 ClassDefPtr base;
8497 if(!bases.empty() && !bases.front()->isInterface())
8498 {
8499 base = bases.front();
8500 }
8501 bool basePreserved = p->inheritsMetaData("preserve-slice");
8502 bool preserved = p->hasMetaData("preserve-slice");
8503
8504 if(preserved && !basePreserved)
8505 {
8506 H << sp;
8507 H << nl << "/**";
8508 H << nl << " * Obtains the SlicedData object created when an unknown value type was marshaled";
8509 H << nl << " * in the sliced format and the Ice run time sliced it to a known type.";
8510 H << nl << " * @return The SlicedData object, or nil if the value was not sliced or was not";
8511 H << nl << " * marshaled in the sliced format.";
8512 H << nl << " */";
8513 H << nl << "virtual ::std::shared_ptr<" << getUnqualified("::Ice::SlicedData", scope)
8514 << "> ice_getSlicedData() const override;";
8515
8516 C << sp;
8517 C << nl << "::std::shared_ptr<::Ice::SlicedData>" << nl << scoped.substr(2) << "::ice_getSlicedData() const";
8518 C << sb;
8519 C << nl << "return _iceSlicedData;";
8520 C << eb;
8521
8522 H << sp;
8523 H << nl << "/// \\cond STREAM";
8524 H << nl << "virtual void _iceWrite(" << getUnqualified("::Ice::OutputStream*", scope) << ") const override;";
8525 H << nl << "virtual void _iceRead(" << getUnqualified("::Ice::InputStream*", scope) << ") override;";
8526 H << nl << "/// \\endcond";
8527
8528 C << sp;
8529 C << nl << "/// \\cond STREAM";
8530 C << nl << "void" << nl << scoped.substr(2) << "::_iceWrite(" << getUnqualified("::Ice::OutputStream*", scope)
8531 << " ostr) const";
8532 C << sb;
8533 C << nl << "ostr->startValue(_iceSlicedData);";
8534 C << nl << "_iceWriteImpl(ostr);";
8535 C << nl << "ostr->endValue();";
8536 C << eb;
8537
8538 C << sp;
8539 C << nl << "void" << nl << scoped.substr(2) << "::_iceRead(" << getUnqualified("::Ice::InputStream*", scope)
8540 << " istr)";
8541 C << sb;
8542 C << nl << "istr->startValue();";
8543 C << nl << "_iceReadImpl(istr);";
8544 C << nl << "_iceSlicedData = istr->endValue(true);";
8545 C << eb;
8546 C << nl << "/// \\endcond";
8547 }
8548
8549 C << sp;
8550 C << nl << "const ::std::string&" << nl << scoped.substr(2) << "::ice_staticId()";
8551 C << sb;
8552 //
8553 // Use local static so that ice_staticId() is usable during static construction.
8554 //
8555 C << nl << "static const ::std::string typeId = \"" << p->scoped() << "\";";
8556 C << nl << "return typeId;";
8557 C << eb;
8558
8559 //
8560 // Emit data members. Access visibility may be specified by metadata.
8561 //
8562 bool inProtected = false;
8563 bool generateFriend = false;
8564 DataMemberList dataMembers = p->dataMembers();
8565 bool prot = p->hasMetaData("protected");
8566 bool needSp = true;
8567
8568 for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
8569 {
8570 if(prot || (*q)->hasMetaData("protected"))
8571 {
8572 if(!inProtected)
8573 {
8574 H.dec();
8575 H << sp << nl << "protected:" << sp;
8576 H.inc();
8577 inProtected = true;
8578 needSp = false;
8579 }
8580 generateFriend = true;
8581 }
8582 else
8583 {
8584 if(inProtected)
8585 {
8586 H.dec();
8587 H << sp << nl << "public:" << sp;
8588 H.inc();
8589 inProtected = false;
8590 needSp = false;
8591 }
8592 }
8593
8594 if(needSp)
8595 {
8596 H << sp;
8597 needSp = false;
8598 }
8599
8600 emitDataMember(*q);
8601 }
8602
8603 if(preserved && !basePreserved)
8604 {
8605 if(!inProtected)
8606 {
8607 H.dec();
8608 H << sp << nl << "protected:";
8609 H.inc();
8610 inProtected = true;
8611 }
8612 H << sp;
8613 H << nl << "/// \\cond STREAM";
8614 H << nl << "::std::shared_ptr<" << getUnqualified("::Ice::SlicedData", scope) << "> _iceSlicedData;";
8615 H << nl << "/// \\endcond";
8616 }
8617
8618 if(generateFriend)
8619 {
8620 if(!inProtected)
8621 {
8622 H.dec();
8623 H << sp << nl << "protected:";
8624 H.inc();
8625 inProtected = true;
8626 }
8627
8628 H << sp;
8629 H << nl << "template<typename T, typename S>";
8630 H << nl << "friend struct Ice::StreamWriter;";
8631 H << nl << "template<typename T, typename S>";
8632 H << nl << "friend struct Ice::StreamReader;";
8633 }
8634
8635 H << eb << ';';
8636
8637 if(!_doneStaticSymbol)
8638 {
8639 //
8640 // We need an instance here to trigger initialization if the implementation is in a static library.
8641 // But we do this only once per source file, because a single instance is sufficient to initialize
8642 // all of the globals in a compilation unit.
8643 //
8644 _doneStaticSymbol = true;
8645 H << sp;
8646 H << nl << "/// \\cond INTERNAL";
8647 H << nl << "static " << fixKwd(p->name()) << " _iceS_" << p->name() << "_init;";
8648 H << nl << "/// \\endcond";
8649 }
8650
8651 _useWstring = resetUseWstring(_useWstringHist);
8652 }
8653
8654 bool
visitExceptionStart(const ExceptionPtr &)8655 Slice::Gen::Cpp11ValueVisitor::visitExceptionStart(const ExceptionPtr&)
8656 {
8657 return false;
8658 }
8659
8660 bool
visitStructStart(const StructPtr &)8661 Slice::Gen::Cpp11ValueVisitor::visitStructStart(const StructPtr&)
8662 {
8663 return false;
8664 }
8665
8666 void
visitOperation(const OperationPtr & p)8667 Slice::Gen::Cpp11ValueVisitor::visitOperation(const OperationPtr& p)
8668 {
8669 emitOpNameResult(H, p, _useWstring);
8670 }
8671
8672 bool
emitVirtualBaseInitializers(const ClassDefPtr & derived,const ClassDefPtr & base)8673 Slice::Gen::Cpp11ObjectVisitor::emitVirtualBaseInitializers(const ClassDefPtr& derived, const ClassDefPtr& base)
8674 {
8675 const string scope = fixKwd(derived->scope());
8676 DataMemberList allDataMembers = base->allDataMembers();
8677 if(allDataMembers.empty())
8678 {
8679 return false;
8680 }
8681
8682 string upcall = "(";
8683 for(DataMemberList::const_iterator q = allDataMembers.begin(); q != allDataMembers.end(); ++q)
8684 {
8685 if(q != allDataMembers.begin())
8686 {
8687 upcall += ", ";
8688 }
8689 if(isMovable((*q)->type()))
8690 {
8691 upcall += "::std::move(" + fixKwd((*q)->name()) + ")";
8692 }
8693 else
8694 {
8695 upcall += "" + fixKwd((*q)->name());
8696 }
8697 }
8698 upcall += ")";
8699
8700 if(base->isLocal())
8701 {
8702 H << nl << getUnqualified(fixKwd(base->scoped()), scope);
8703 }
8704 else
8705 {
8706 H << nl << "Ice::ValueHelper<" << getUnqualified(fixKwd(derived->scoped()), scope)
8707 << ", " << getUnqualified(fixKwd(base->scoped()), scope) << ">";
8708 }
8709 H << upcall;
8710 return true;
8711 }
8712
8713 void
emitOneShotConstructor(const ClassDefPtr & p)8714 Slice::Gen::Cpp11ObjectVisitor::emitOneShotConstructor(const ClassDefPtr& p)
8715 {
8716 DataMemberList allDataMembers = p->allDataMembers();
8717 string scope = fixKwd(p->scope());
8718 if(!allDataMembers.empty())
8719 {
8720 vector<string> allParamDecls;
8721 map<string, CommentPtr> allComments;
8722 DataMemberList dataMembers = p->dataMembers();
8723
8724 int typeContext = _useWstring | TypeContextCpp11;
8725 if(p->isLocal())
8726 {
8727 typeContext |= TypeContextLocal;
8728 }
8729
8730 for(DataMemberList::const_iterator q = allDataMembers.begin(); q != allDataMembers.end(); ++q)
8731 {
8732 string typeName =
8733 inputTypeToString((*q)->type(), (*q)->optional(), scope, (*q)->getMetaData(), typeContext);
8734 allParamDecls.push_back(typeName + " " + fixKwd((*q)->name()));
8735 CommentPtr comment = (*q)->parseComment(false);
8736 if(comment)
8737 {
8738 allComments[(*q)->name()] = comment;
8739 }
8740 }
8741
8742 CommentPtr comment = p->parseComment(false);
8743
8744 H << sp;
8745 H << nl << "/**";
8746 H << nl << " * One-shot constructor to initialize all data members.";
8747 for(DataMemberList::const_iterator q = allDataMembers.begin(); q != allDataMembers.end(); ++q)
8748 {
8749 map<string, CommentPtr>::iterator r = allComments.find((*q)->name());
8750 if(r != allComments.end())
8751 {
8752 H << nl << " * @param " << fixKwd(r->first) << " " << getDocSentence(r->second->overview());
8753 }
8754 }
8755 H << nl << " */";
8756 H << nl;
8757 if(allParamDecls.size() == 1)
8758 {
8759 H << "explicit ";
8760 }
8761 H << fixKwd(p->name()) << spar << allParamDecls << epar << " :";
8762 H.inc();
8763
8764 ClassList bases = p->bases();
8765
8766 if(!bases.empty() && !bases.front()->isInterface())
8767 {
8768 if(emitVirtualBaseInitializers(p, bases.front()))
8769 {
8770 if(!dataMembers.empty())
8771 {
8772 H << ',';
8773 }
8774 }
8775 }
8776
8777 if(!dataMembers.empty())
8778 {
8779 H << nl;
8780 }
8781
8782 for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
8783 {
8784 if(q != dataMembers.begin())
8785 {
8786 H << ',' << nl;
8787 }
8788 string memberName = fixKwd((*q)->name());
8789 if(isMovable((*q)->type()))
8790 {
8791 H << memberName << "(::std::move(" << memberName << "))";
8792 }
8793 else
8794 {
8795 H << memberName << "(" << memberName << ')';
8796 }
8797 }
8798
8799 H.dec();
8800 H << sb;
8801 H << eb;
8802 }
8803 }
8804
Cpp11StreamVisitor(Output & h,Output & c,const string & dllExport)8805 Slice::Gen::Cpp11StreamVisitor::Cpp11StreamVisitor(Output& h, Output& c, const string& dllExport) :
8806 H(h),
8807 C(c),
8808 _dllExport(dllExport)
8809 {
8810 }
8811
8812 bool
visitModuleStart(const ModulePtr & m)8813 Slice::Gen::Cpp11StreamVisitor::visitModuleStart(const ModulePtr& m)
8814 {
8815 if(!m->hasNonLocalContained(Contained::ContainedTypeStruct) &&
8816 !m->hasNonLocalContained(Contained::ContainedTypeEnum) &&
8817 !m->hasNonLocalContained(Contained::ContainedTypeException) &&
8818 !m->hasNonLocalContained(Contained::ContainedTypeClass))
8819 {
8820 return false;
8821 }
8822
8823 if(UnitPtr::dynamicCast(m->container()))
8824 {
8825 //
8826 // Only emit this for the top-level module.
8827 //
8828 H << sp;
8829 H << nl << "/// \\cond STREAM";
8830 H << nl << "namespace Ice" << nl << '{' << sp;
8831
8832 if(m->hasNonLocalContained(Contained::ContainedTypeStruct))
8833 {
8834 C << sp;
8835 C << nl << "namespace Ice" << nl << '{';
8836 }
8837 }
8838 return true;
8839 }
8840
8841 void
visitModuleEnd(const ModulePtr & m)8842 Slice::Gen::Cpp11StreamVisitor::visitModuleEnd(const ModulePtr& m)
8843 {
8844 if(UnitPtr::dynamicCast(m->container()))
8845 {
8846 //
8847 // Only emit this for the top-level module.
8848 //
8849 H << nl << '}';
8850 H << nl << "/// \\endcond";
8851 if(m->hasNonLocalContained(Contained::ContainedTypeStruct))
8852 {
8853 C << nl << '}';
8854 }
8855 }
8856 }
8857
8858 bool
visitStructStart(const StructPtr & p)8859 Slice::Gen::Cpp11StreamVisitor::visitStructStart(const StructPtr& p)
8860 {
8861 if(p->isLocal())
8862 {
8863 return false;
8864 }
8865
8866 string scoped = fixKwd(p->scoped());
8867
8868 H << nl << "template<>";
8869 H << nl << "struct StreamableTraits<" << scoped << ">";
8870 H << sb;
8871 H << nl << "static const StreamHelperCategory helper = StreamHelperCategoryStruct;";
8872 H << nl << "static const int minWireSize = " << p->minWireSize() << ";";
8873 H << nl << "static const bool fixedLength = " << (p->isVariableLength() ? "false" : "true") << ";";
8874 H << eb << ";" << nl;
8875
8876 writeStreamHelpers(H, p, p->dataMembers(), false, false, true);
8877
8878 return false;
8879 }
8880
8881 bool
visitClassDefStart(const ClassDefPtr & c)8882 Slice::Gen::Cpp11StreamVisitor::visitClassDefStart(const ClassDefPtr& c)
8883 {
8884 if(!c->isLocal() && !c->isInterface())
8885 {
8886 writeStreamHelpers(H,c, c->dataMembers(), c->hasBaseDataMembers(), true, true);
8887 }
8888 return false;
8889 }
8890
8891 void
visitExceptionEnd(const ExceptionPtr & p)8892 Slice::Gen::Cpp11StreamVisitor::visitExceptionEnd(const ExceptionPtr& p)
8893 {
8894 if(!p->isLocal())
8895 {
8896 writeStreamHelpers(H,p, p->dataMembers(), p->hasBaseDataMembers(), true, true);
8897 }
8898 }
8899
8900 void
visitEnum(const EnumPtr & p)8901 Slice::Gen::Cpp11StreamVisitor::visitEnum(const EnumPtr& p)
8902 {
8903 if(!p->isLocal())
8904 {
8905 string scoped = fixKwd(p->scoped());
8906 H << nl << "template<>";
8907 H << nl << "struct StreamableTraits< " << scoped << ">";
8908 H << sb;
8909 H << nl << "static const StreamHelperCategory helper = StreamHelperCategoryEnum;";
8910 H << nl << "static const int minValue = " << p->minValue() << ";";
8911 H << nl << "static const int maxValue = " << p->maxValue() << ";";
8912 H << nl << "static const int minWireSize = " << p->minWireSize() << ";";
8913 H << nl << "static const bool fixedLength = false;";
8914 H << eb << ";" << nl;
8915 }
8916 }
8917
Cpp11CompatibilityVisitor(Output & h,Output &,const string & dllExport)8918 Slice::Gen::Cpp11CompatibilityVisitor::Cpp11CompatibilityVisitor(Output& h, Output&, const string& dllExport) :
8919 H(h),
8920 _dllExport(dllExport)
8921 {
8922 }
8923
8924 bool
visitModuleStart(const ModulePtr & p)8925 Slice::Gen::Cpp11CompatibilityVisitor::visitModuleStart(const ModulePtr& p)
8926 {
8927 if(!p->hasClassDecls())
8928 {
8929 return false;
8930 }
8931
8932 string name = fixKwd(p->name());
8933
8934 H << sp;
8935 H << nl << "/// \\cond INTERNAL";
8936 H << nl << "namespace " << name << nl << '{';
8937 return true;
8938 }
8939
8940 void
visitModuleEnd(const ModulePtr &)8941 Slice::Gen::Cpp11CompatibilityVisitor::visitModuleEnd(const ModulePtr&)
8942 {
8943 H << sp;
8944 H << nl << '}';
8945 H << nl << "/// \\endcond";
8946 }
8947
8948 void
visitClassDecl(const ClassDeclPtr & p)8949 Slice::Gen::Cpp11CompatibilityVisitor::visitClassDecl(const ClassDeclPtr& p)
8950 {
8951 if(p->definition() && p->definition()->isDelegate())
8952 {
8953 return;
8954 }
8955
8956 string name = fixKwd(p->name());
8957 string scoped = fixKwd(p->scoped());
8958
8959 H << sp << nl << "using " << p->name() << "Ptr = ::std::shared_ptr<" << name << ">;";
8960
8961 if(!p->isLocal())
8962 {
8963 ClassDefPtr def = p->definition();
8964 if(p->isInterface() || (def && !def->allOperations().empty()))
8965 {
8966 H << nl << "using " << p->name() << "PrxPtr = ::std::shared_ptr<" << p->name() << "Prx>;";
8967 }
8968 }
8969 }
8970
Cpp11ImplVisitor(Output & h,Output & c,const string & dllExport)8971 Slice::Gen::Cpp11ImplVisitor::Cpp11ImplVisitor(Output& h, Output& c, const string& dllExport) :
8972 H(h), C(c), _dllExport(dllExport), _useWstring(false)
8973 {
8974 }
8975
8976 string
defaultValue(const TypePtr & type,const string & scope,const StringList & metaData) const8977 Slice::Gen::Cpp11ImplVisitor::defaultValue(const TypePtr& type, const string& scope, const StringList& metaData) const
8978 {
8979 BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
8980 if(builtin)
8981 {
8982 switch(builtin->kind())
8983 {
8984 case Builtin::KindBool:
8985 {
8986 return "false";
8987 }
8988 case Builtin::KindByte:
8989 case Builtin::KindShort:
8990 case Builtin::KindInt:
8991 case Builtin::KindLong:
8992 {
8993 return "0";
8994 }
8995 case Builtin::KindFloat:
8996 case Builtin::KindDouble:
8997 {
8998 return "0.0";
8999 }
9000 case Builtin::KindString:
9001 {
9002 return "::std::string()";
9003 }
9004 case Builtin::KindValue:
9005 case Builtin::KindObject:
9006 case Builtin::KindObjectProxy:
9007 case Builtin::KindLocalObject:
9008 {
9009 return "nullptr";
9010 }
9011 }
9012 }
9013 else
9014 {
9015 ProxyPtr prx = ProxyPtr::dynamicCast(type);
9016
9017 if(ProxyPtr::dynamicCast(type) || ClassDeclPtr::dynamicCast(type))
9018 {
9019 return "nullptr";
9020 }
9021
9022 StructPtr st = StructPtr::dynamicCast(type);
9023 if(st)
9024 {
9025 return getUnqualified(fixKwd(st->scoped()), scope) + "()";
9026 }
9027
9028 EnumPtr en = EnumPtr::dynamicCast(type);
9029 if(en)
9030 {
9031 EnumeratorList enumerators = en->enumerators();
9032 return getUnqualified(fixKwd(en->scoped() + "::" + enumerators.front()->name()), scope);
9033 }
9034
9035 SequencePtr seq = SequencePtr::dynamicCast(type);
9036 if(seq)
9037 {
9038 return typeToString(seq, scope, metaData, _useWstring | TypeContextCpp11) + "()";
9039 }
9040
9041 DictionaryPtr dict = DictionaryPtr::dynamicCast(type);
9042 if(dict)
9043 {
9044 return getUnqualified(fixKwd(dict->scoped()), scope) + "()";
9045 }
9046 }
9047
9048 assert(false);
9049 return "???";
9050 }
9051
9052 bool
visitModuleStart(const ModulePtr & p)9053 Slice::Gen::Cpp11ImplVisitor::visitModuleStart(const ModulePtr& p)
9054 {
9055 if(!p->hasClassDefs())
9056 {
9057 return false;
9058 }
9059
9060 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
9061
9062 string name = fixKwd(p->name());
9063
9064 H << sp << nl << "namespace " << name << nl << '{';
9065
9066 return true;
9067 }
9068
9069 void
visitModuleEnd(const ModulePtr &)9070 Slice::Gen::Cpp11ImplVisitor::visitModuleEnd(const ModulePtr&)
9071 {
9072 H << sp;
9073 H << nl << '}';
9074
9075 _useWstring = resetUseWstring(_useWstringHist);
9076 }
9077
9078 bool
visitClassDefStart(const ClassDefPtr & p)9079 Slice::Gen::Cpp11ImplVisitor::visitClassDefStart(const ClassDefPtr& p)
9080 {
9081 if(!p->isAbstract())
9082 {
9083 return false;
9084 }
9085
9086 _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
9087
9088 string name = p->name();
9089 string scoped = fixKwd(p->scoped());
9090 string scope = fixKwd(p->scope());
9091 string cls = scope.substr(2) + name + "I";
9092 ClassList bases = p->bases();
9093
9094 H << sp;
9095 H << nl << "class " << name << "I : ";
9096 H.useCurrentPosAsIndent();
9097 H << "public virtual ";
9098
9099 if(p->isInterface() || p->isLocal())
9100 {
9101 H << fixKwd(name);
9102 }
9103 else
9104 {
9105 H << fixKwd(name + "Disp");
9106 }
9107 H.restoreIndent();
9108
9109 H << sb;
9110 H.dec();
9111 H << nl << "public:";
9112 H.inc();
9113
9114 OperationList ops = p->allOperations();
9115
9116 for(OperationList::const_iterator r = ops.begin(); r != ops.end(); ++r)
9117 {
9118 OperationPtr op = (*r);
9119 string opName = op->name();
9120
9121 TypePtr ret = op->returnType();
9122 string retS = op->hasMarshaledResult() ?
9123 scoped + "::" + resultStructName(opName, "", true) :
9124 returnTypeToString(ret, op->returnIsOptional(), "", op->getMetaData(), _useWstring | TypeContextCpp11);
9125
9126 ParamDeclList params = op->parameters();
9127 ParamDeclList outParams;
9128 ParamDeclList inParams;
9129 for(ParamDeclList::const_iterator q = params.begin(); q != params.end(); ++q)
9130 {
9131 if((*q)->isOutParam())
9132 {
9133 outParams.push_back(*q);
9134 }
9135 else
9136 {
9137 inParams.push_back(*q);
9138 }
9139 }
9140
9141 if(!p->isLocal() && (p->hasMetaData("amd") || op->hasMetaData("amd")))
9142 {
9143 string responseParams;
9144
9145 H << sp << nl << "virtual void " << opName << "Async(";
9146 H.useCurrentPosAsIndent();
9147 for(ParamDeclList::const_iterator q = inParams.begin(); q != inParams.end(); ++q)
9148 {
9149 H << typeToString((*q)->type(), (*q)->optional(), scope,
9150 (*q)->getMetaData(), _useWstring | TypeContextInParam | TypeContextCpp11)
9151 << "," << nl;
9152 }
9153
9154 if(op->hasMarshaledResult())
9155 {
9156 responseParams = "const " + scoped + "::" + resultStructName(opName, "", true) + "&";
9157 }
9158 else
9159 {
9160 if(ret)
9161 {
9162 responseParams = inputTypeToString(ret, op->returnIsOptional(), scope, op->getMetaData(),
9163 _useWstring | TypeContextCpp11);
9164 if(!outParams.empty())
9165 {
9166 responseParams += ", ";
9167 }
9168 }
9169
9170 for(ParamDeclList::iterator q = outParams.begin(); q != outParams.end(); ++q)
9171 {
9172 if(q != outParams.begin())
9173 {
9174 responseParams += ", ";
9175 }
9176 responseParams += inputTypeToString((*q)->type(), (*q)->optional(), scope, (*q)->getMetaData(),
9177 _useWstring | TypeContextCpp11);
9178 }
9179 }
9180
9181 string isConst = ((op->mode() == Operation::Nonmutating) || op->hasMetaData("cpp:const")) ? " const" : "";
9182
9183 H << "std::function<void(" << responseParams << ")>,";
9184 H << nl << "std::function<void(std::exception_ptr)>,";
9185 H << nl << "const Ice::Current&)" << isConst << " override;";
9186 H.restoreIndent();
9187
9188 C << sp << nl << "void" << nl << scope << name << "I::" << opName << "Async(";
9189 C.useCurrentPosAsIndent();
9190 for(ParamDeclList::const_iterator q = inParams.begin(); q != inParams.end(); ++q)
9191 {
9192 C << typeToString((*q)->type(), (*q)->optional(), scope, (*q)->getMetaData(),
9193 _useWstring | TypeContextInParam | TypeContextCpp11);
9194 C << ' ' << fixKwd((*q)->name()) << "," << nl;
9195 }
9196
9197 C << "std::function<void(" << responseParams << ")> " << opName << "_response,";
9198 C << nl << "std::function<void(std::exception_ptr)>,";
9199 C << nl << "const Ice::Current& current)" << isConst;
9200 C.restoreIndent();
9201 C << sb;
9202
9203 C << nl << opName << "_response";
9204 if(op->hasMarshaledResult())
9205 {
9206 C << "(" << scoped + "::" + resultStructName(opName, "", true);
9207 }
9208 C << spar;
9209 if(ret)
9210 {
9211 C << defaultValue(ret, scope, op->getMetaData());
9212 }
9213 for(ParamDeclList::const_iterator q = outParams.begin(); q != outParams.end(); ++q)
9214 {
9215 C << defaultValue((*q)->type(), scope, op->getMetaData());
9216 }
9217
9218 if(op->hasMarshaledResult())
9219 {
9220 C << "current" << epar << ");";
9221 }
9222 else
9223 {
9224 C << epar << ';';
9225 }
9226
9227 C << eb;
9228 }
9229 else
9230 {
9231 H << sp << nl << "virtual " << getUnqualified(retS, scope) << ' ' << fixKwd(opName) << '(';
9232 H.useCurrentPosAsIndent();
9233 ParamDeclList paramList = op->hasMarshaledResult() ? inParams : op->parameters();
9234 for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
9235 {
9236 if(q != paramList.begin())
9237 {
9238 H << ',' << nl;
9239 }
9240 StringList metaData = (*q)->getMetaData();
9241 string typeString;
9242 if((*q)->isOutParam())
9243 {
9244 typeString = outputTypeToString((*q)->type(), (*q)->optional(), scope, metaData,
9245 _useWstring | TypeContextCpp11);
9246 }
9247 else
9248 {
9249 typeString = typeToString((*q)->type(), (*q)->optional(), scope, metaData,
9250 _useWstring | TypeContextInParam | TypeContextCpp11);
9251 }
9252 H << typeString;
9253 }
9254 if(!p->isLocal())
9255 {
9256 if(!paramList.empty())
9257 {
9258 H << ',' << nl;
9259 }
9260 H << "const Ice::Current&";
9261 }
9262 H.restoreIndent();
9263
9264 string isConst = ((op->mode() == Operation::Nonmutating) || op->hasMetaData("cpp:const")) ? " const" : "";
9265
9266 H << ")" << isConst << " override;";
9267
9268 C << sp << nl << retS << nl;
9269 C << scope.substr(2) << name << "I::" << fixKwd(opName) << '(';
9270 C.useCurrentPosAsIndent();
9271 for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
9272 {
9273 if(q != paramList.begin())
9274 {
9275 C << ',' << nl;
9276 }
9277 StringList metaData = (*q)->getMetaData();
9278 string typeString;
9279 if((*q)->isOutParam())
9280 {
9281 C << outputTypeToString((*q)->type(), (*q)->optional(), scope, metaData, _useWstring | TypeContextCpp11)
9282 << " "
9283 << fixKwd((*q)->name());
9284 }
9285 else
9286 {
9287 C << typeToString((*q)->type(), (*q)->optional(), scope, metaData,
9288 _useWstring | TypeContextInParam | TypeContextCpp11)
9289 << " /*" << fixKwd((*q)->name()) << "*/";
9290 }
9291 }
9292 if(!p->isLocal())
9293 {
9294 if(!paramList.empty())
9295 {
9296 C << ',' << nl;
9297 }
9298 C << "const Ice::Current& current";
9299 }
9300 C.restoreIndent();
9301 C << ')';
9302 C << isConst;
9303 C << sb;
9304
9305 if(op->hasMarshaledResult())
9306 {
9307 if(ret || !outParams.empty())
9308 {
9309 C << nl << "return " << scoped << "::" << resultStructName(opName, "", true) << "(";
9310 if(ret)
9311 {
9312 C << defaultValue(ret, scope, op->getMetaData());
9313 if(!outParams.empty())
9314 {
9315 C << ", ";
9316 }
9317 }
9318
9319 for(ParamDeclList::const_iterator q = outParams.begin(); q != outParams.end();)
9320 {
9321 C << defaultValue((*q)->type(), scope, op->getMetaData());
9322 if(++q != outParams.end())
9323 {
9324 C << ", ";
9325 }
9326 }
9327 C << ", current);";
9328 }
9329 }
9330 else
9331 {
9332 for(ParamDeclList::const_iterator q = outParams.begin(); q != outParams.end(); ++q)
9333 {
9334 C << nl << fixKwd((*q)->name()) << " = " << defaultValue((*q)->type(), scope, op->getMetaData()) << ";";
9335 }
9336
9337 if(ret)
9338 {
9339 C << nl << "return " << defaultValue(ret, scope, op->getMetaData()) << ";";
9340 }
9341 }
9342 C << eb;
9343 }
9344 }
9345
9346 H << eb << ';';
9347
9348 _useWstring = resetUseWstring(_useWstringHist);
9349
9350 return true;
9351 }
9352