1
|
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 }
|