comparison generator/containergenerator.cpp @ 1:e78566595089

initial import
author mandel
date Mon, 11 May 2009 16:01:50 +0000
parents
children 5917a613d118
comparison
equal deleted inserted replaced
0:36fb74dc547d 1:e78566595089
1 /****************************************************************************
2 **
3 ** Copyright (C) 1992-2008 Nokia. All rights reserved.
4 **
5 ** This file is part of Qt Jambi.
6 **
7 ** * Commercial Usage
8 * Licensees holding valid Qt Commercial licenses may use this file in
9 * accordance with the Qt Commercial License Agreement provided with the
10 * Software or, alternatively, in accordance with the terms contained in
11 * a written agreement between you and Nokia.
12 *
13 *
14 * GNU General Public License Usage
15 * Alternatively, this file may be used under the terms of the GNU
16 * General Public License versions 2.0 or 3.0 as published by the Free
17 * Software Foundation and appearing in the file LICENSE.GPL included in
18 * the packaging of this file. Please review the following information
19 * to ensure GNU General Public Licensing requirements will be met:
20 * http://www.fsf.org/licensing/licenses/info/GPLv2.html and
21 * http://www.gnu.org/copyleft/gpl.html. In addition, as a special
22 * exception, Nokia gives you certain additional rights. These rights
23 * are described in the Nokia Qt GPL Exception version 1.2, included in
24 * the file GPL_EXCEPTION.txt in this package.
25 *
26 * Qt for Windows(R) Licensees
27 * As a special exception, Nokia, as the sole copyright holder for Qt
28 * Designer, grants users of the Qt/Eclipse Integration plug-in the
29 * right for the Qt/Eclipse Integration to link to functionality
30 * provided by Qt Designer and its related libraries.
31 *
32 *
33 * If you are unsure which license is appropriate for your use, please
34 * contact the sales department at qt-sales@nokia.com.
35
36 **
37 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
38 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
39 **
40 ****************************************************************************/
41
42 #include "containergenerator.h"
43 #include "cppimplgenerator.h"
44 #include "fileout.h"
45
46 static Indentor INDENT;
47
48 ContainerGenerator::ContainerGenerator():
49 DGenerator()
50
51 {
52 setFilenameStub("ArrayOps");
53 excludedTypes.clear();
54
55 // qtd2
56 excludedTypes << "QFuture";
57 }
58
59 QString ContainerGenerator::subDirectoryForPackage(const QString &package, OutputDirectoryType type) const
60 {
61 switch (type) {
62 case CppDirectory:
63 return "cpp/" + QString(package).replace(".", "_") + "/";
64 case DDirectory:
65 return QString(package).replace(".", "/");
66 case HDirectory:
67 return "include/";
68 default:
69 return QString(); // kill nonsense warnings
70 }
71 }
72
73 void ContainerGenerator::write(QTextStream &, const AbstractMetaClass *)
74 {
75 // not used
76 }
77
78 void ContainerGenerator::addTypeEntry(const TypeEntry* te)
79 {
80 if (!excludedTypes.contains(te->name()))
81 containerTypes << te;
82 }
83
84 void ContainerGenerator::processType(AbstractMetaType *d_type)
85 {
86 if (d_type->isContainer()) {
87 QList<AbstractMetaType *> args = d_type->instantiations();
88
89 if (args.size() == 1) // QVector or QList
90 if (args.at(0)->typeEntry()->isComplex()
91 && !args.at(0)->isContainer()
92 && !args.at(0)->isTargetLangString())
93 addTypeEntry(args.at(0)->typeEntry()); // qMakePair(args.at(0)->typeEntry(), m_class);
94 }
95 }
96
97 void ContainerGenerator::processFunction(const AbstractMetaFunction *d_function)
98 {
99 if (notWrappedYet(d_function)) // qtd2
100 return;
101
102 if (d_function->type()) {
103 AbstractMetaType *d_type = d_function->type();
104 if (d_type->isContainer()) {
105 processType(d_type);
106 }
107 }
108
109 AbstractMetaArgumentList arguments = d_function->arguments();
110 for (int i=0; i<arguments.count(); ++i) {
111 const AbstractMetaArgument *arg = arguments.at(i);
112 processType(arg->type());
113 }
114 }
115
116 void ContainerGenerator::buildTypeList()
117 {
118 foreach (AbstractMetaClass *d_class, classes()) {
119 m_class = d_class;
120 AbstractMetaFunctionList d_funcs = d_class->functionsInTargetLang();
121 for (int i=0; i<d_funcs.size(); ++i) {
122 AbstractMetaFunction *function = d_funcs.at(i);
123
124 // If a method in an interface class is modified to be private, this should
125 // not be present in the interface at all, only in the implementation.
126 if (d_class->isInterface()) {
127 uint includedAttributes = 0;
128 uint excludedAttributes = 0;
129 retrieveModifications(function, d_class, &excludedAttributes, &includedAttributes);
130 if (includedAttributes & AbstractMetaAttributes::Private)
131 continue;
132 }
133
134 processFunction(function);
135 }
136 AbstractMetaFieldList fields = d_class->fields();
137 foreach (const AbstractMetaField *field, fields) {
138 if (field->wasPublic() || (field->wasProtected() && !d_class->isFinal())) {
139 processFunction(field->setter());
140 processFunction(field->getter());
141 }
142 }
143
144 }
145 }
146
147 void ContainerGenerator::generate()
148 {
149 buildTypeList();
150
151 writeFile(cppFilename(), CppDirectory, &ContainerGenerator::writeCppContent); // cpp file
152 writeFile("ArrayOps_%1.h", HDirectory, &ContainerGenerator::writeHeaderContent); // header file
153 writeFile(dFilename(), DDirectory, &ContainerGenerator::writeDContent); // d file
154 }
155
156 void ContainerGenerator::writeFile(const QString& fileName, OutputDirectoryType dirType, WriteOut writeOut)
157 {
158 AbstractMetaClassList classList = classes();
159 QHash<QString, FileOut *> fileHash;
160
161 // Seems continue is not supported by our foreach loop, so
162 foreach (AbstractMetaClass *cls, classList) {
163
164 FileOut *f = fileHash.value(cls->package(), 0);
165 if (f == 0) {
166 f = new FileOut(outputDirectory() + "/" + subDirectoryForPackage(cls->package(), dirType) + "/" +
167 fileName.arg(cls->package().replace(".", "_")));
168 writeNotice(f->stream);
169
170 (this->*writeOut)(f->stream, cls);
171
172 fileHash.insert(cls->package(), f);
173
174 // QString pro_file_name = cls->package().replace(".", "_") + "/" + cls->package().replace(".", "_") + ".pri";
175 // priGenerator->addSource(pro_file_name, cppFilename());
176 }
177 }
178
179 foreach (QString package, fileHash.keys()) {
180 FileOut *f = fileHash.value(package, 0);
181 if (f != 0) {
182 if( f->done() )
183 ++m_num_generated_written;
184 ++m_num_generated;
185
186 delete f;
187 }
188 }
189 }
190
191 void ContainerGenerator::writeCppContent(QTextStream &s, AbstractMetaClass *cls)
192 {
193 QString package = cls->package().replace(".", "_");
194
195 s << "// stuff for passing D function pointers" << endl << endl
196 << "#ifdef CPP_SHARED" << endl << endl
197 << "#include \"ArrayOps_" << package << ".h\"" << endl << endl;
198
199 foreach (const TypeEntry *te, containerTypes) {
200 if (te->javaPackage() == cls->package()) {
201 const ComplexTypeEntry *centry = static_cast<const ComplexTypeEntry *>(te);
202 QString cls_name = centry->name();
203
204 setFuncNames(cls_name);
205 s << "QTD_EXPORT_VAR(" << all_name << ")" << endl
206 << "QTD_EXPORT_VAR(" << ass_name << ")" << endl
207 << "QTD_EXPORT_VAR(" << get_name << ")" << endl << endl;
208 }
209 }
210
211 s << endl
212 << "extern \"C\" DLL_PUBLIC void qtd_" << cls->package().replace(".", "_") << "_ArrayOps_initCallBacks(pfunc_abstr *callbacks)" << endl
213 << "{" << endl;
214
215 int num_funcs = 0;
216 foreach (const TypeEntry *te, containerTypes) {
217 if (te->javaPackage() == cls->package()) {
218 const ComplexTypeEntry *centry = static_cast<const ComplexTypeEntry *>(te);
219 QString cls_name = centry->name();
220
221 setFuncNames(cls_name);
222 s << " QTD_EXPORT_VAR_SET(" << all_name << ", callbacks[" << num_funcs + 0 << "]);" << endl
223 << " QTD_EXPORT_VAR_SET(" << ass_name << ", callbacks[" << num_funcs + 1 << "]);" << endl
224 << " QTD_EXPORT_VAR_SET(" << get_name << ", callbacks[" << num_funcs + 2 << "]);" << endl << endl;
225
226 num_funcs += NUM_ARRAY_FUNCS;
227 }
228 }
229 s << "}" << endl
230 << "#endif" << endl;
231 }
232
233 void ContainerGenerator::writeHeaderContent(QTextStream &s, AbstractMetaClass *cls)
234 {
235 s << "#include <cstring>" << endl
236 << "#include \"qtd_core.h\"" << endl << endl;
237
238 foreach (const TypeEntry *te, containerTypes) {
239 if (te->javaPackage() == cls->package()) {
240 const ComplexTypeEntry *typeEntry = static_cast<const ComplexTypeEntry *>(te);
241 s << "// " << typeEntry->name() << endl; // " in " << it.second->name() << endl;
242
243 Indentation indent(INDENT);
244 writeHeaderArrayFunctions(s, typeEntry);
245 }
246 }
247 }
248
249 void ContainerGenerator::setFuncNames(const QString& cls_name)
250 {
251 all_name = QString("qtd_allocate_%1_array").arg(cls_name);
252 ass_name = QString("qtd_assign_%1_array_element").arg(cls_name);
253 get_name = QString("qtd_get_%1_from_array").arg(cls_name);
254 }
255
256 void ContainerGenerator::writeHeaderArrayFunctions(QTextStream &s, const ComplexTypeEntry *centry)
257 {
258 QString cls_name = centry->name();
259 bool d_export = true;
260 QString d_type, cpp_type, cpp_type_assign;
261
262 if (centry->name() == "QModelIndex") {
263 cpp_type = "QModelIndexAccessor*";
264 } else if (centry->isStructInD()) {
265 cpp_type = centry->qualifiedCppName() + "*";
266 } else if (centry->isObject() || centry->isQObject() || centry->isValue() || centry->isInterface() || centry->isVariant()) {
267 cpp_type = "void*";
268 }
269
270 setFuncNames(cls_name);
271
272 s << "QTD_EXPORT(void, " << all_name << ", (void* arr, size_t len))" << endl
273 << "QTD_EXPORT(void, " << ass_name << ", (void* arr, size_t pos, " << cpp_type << " elem))" << endl
274 << "QTD_EXPORT(void, " << get_name << ", (void* arr, size_t pos, " << cpp_type << " elem))" << endl;
275
276 s << "#ifdef CPP_SHARED" << endl
277 << "#define " << all_name << " qtd_get_" << all_name << "()" << endl
278 << "#define " << ass_name << " qtd_get_" << ass_name << "()" << endl
279 << "#define " << get_name << " qtd_get_" << get_name << "()" << endl
280 << "#endif" << endl;
281
282 s << endl;
283 }
284
285 void ContainerGenerator::writeDContent(QTextStream &s, AbstractMetaClass *cls)
286 {
287 s << "module " << cls->package() << ".ArrayOps;" << endl << endl;
288
289 int num_funcs = 0;
290 foreach (const TypeEntry *te, containerTypes) {
291 if (te->javaPackage() == cls->package()) {
292 const ComplexTypeEntry *typeEntry = static_cast<const ComplexTypeEntry *>(te);
293 s << "// " << typeEntry->name() << endl;
294 writeImportString(s, typeEntry);
295 s << endl;
296
297 Indentation indent(INDENT);
298
299 writeArrayFunctions(s, typeEntry);
300 s << endl;
301 num_funcs += NUM_ARRAY_FUNCS;
302 }
303 }
304 if (num_funcs == 0)
305 return;
306
307 s << "version (Windows) {" << endl
308 << " private extern (C) void qtd_" << cls->package().replace(".", "_") << "_ArrayOps_initCallBacks(void* callbacks);" << endl << endl
309 << " static this() {" << endl
310 << " void*[" << num_funcs << "] callbacks; " << endl << endl;
311
312 num_funcs = 0;
313 foreach (const TypeEntry *te, containerTypes) {
314 if (te->javaPackage() == cls->package()) {
315 const ComplexTypeEntry *centry = static_cast<const ComplexTypeEntry *>(te);
316
317 QString cls_name = centry->name();
318 setFuncNames(cls_name);
319
320 s << " callbacks[" << num_funcs + 0 << "] = &" << all_name << ";" << endl
321 << " callbacks[" << num_funcs + 1 << "] = &" << ass_name << ";" << endl
322 << " callbacks[" << num_funcs + 2 << "] = &" << get_name << ";" << endl;
323
324 s << endl;
325 num_funcs += NUM_ARRAY_FUNCS;
326 }
327 }
328 s << " qtd_" << cls->package().replace(".", "_") << "_ArrayOps_initCallBacks(callbacks.ptr);" << endl
329 << " }" << endl
330 << "}" << endl;
331 }
332
333 void ContainerGenerator::writeNotice(QTextStream &s)
334 {
335 s << "/****************************************************************************" << endl
336 << "**" << endl
337 << "** This is a generated file, please don't touch." << endl
338 << "**" << endl
339 << "****************************************************************************/" << endl << endl;
340 }
341
342 void ContainerGenerator::writeArrayFunctions(QTextStream &s, const ComplexTypeEntry *centry)
343 {
344 QString cls_name = centry->name();
345 QString type_name = cls_name;
346
347 bool d_export = true;
348 QString d_type, cpp_type, cpp_assign_type, convert, nativeId;
349
350 convert = "qtd_" + cls_name + "_cpp_to_d(elem)";
351 nativeId = "";
352
353 if (centry->name() == "QModelIndex") {
354 cpp_type = "QModelIndexAccessor*";
355 cpp_assign_type = cpp_type;
356 d_type = cpp_type;
357 convert = "*elem";
358 } else if (centry->isStructInD()) {
359 cpp_type = centry->qualifiedCppName() + "*";
360 cpp_assign_type = cpp_type;
361 d_type = cpp_type;
362 convert = "*elem";
363 } else if (centry->isObject() || centry->isQObject() || centry->isValue() || centry->isInterface() || centry->isVariant()) {
364 cpp_type = "void*";
365 cpp_assign_type = cpp_type + "*";
366 d_type = cls_name;
367 nativeId = ".nativeId";
368 }
369
370 if (centry->designatedInterface()) {
371 type_name = centry->designatedInterface()->name();
372 nativeId = ".__ptr_" + type_name;
373 }
374
375 s << "private extern(C) void qtd_allocate_" << cls_name << "_array(" << type_name << "[]* arr, size_t len)" << endl
376 << "{" << endl
377 << INDENT << "*arr = new " << type_name << "[len];" << endl
378 << "}" << endl << endl;
379
380 s << "private extern(C) void qtd_assign_" << cls_name << "_array_element(" << type_name << "[]* arr, size_t pos, " << cpp_type << " elem)" << endl
381 << "{" << endl
382 << INDENT << "(*arr)[pos] = " << convert << ";" << endl
383 << "}" << endl << endl
384
385 << "private extern(C) void qtd_get_" << cls_name << "_from_array(" << type_name << "* arr, size_t pos, " << cpp_assign_type << " elem)" << endl
386 << "{" << endl
387 << INDENT << "*elem = arr[pos]" << nativeId << ";" << endl
388 << "}" << endl << endl
389
390 << "package " << d_type << " qtd_" << cls_name << "_cpp_to_d(" << cpp_type << " __qt_return_value)" << endl
391 << "{" << endl;
392
393 marshallFromCppToD(s, centry);
394
395 s << "}" << endl;
396 }