Mercurial > projects > qtd
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 } |