1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qmetaobjectbuilder_p.h"
5
6#include "qobject_p.h"
7#include "qmetaobject_p.h"
8
9#include <vector>
10#include <stdlib.h>
11
12QT_BEGIN_NAMESPACE
13
14/*!
15 \class QMetaObjectBuilder
16 \inmodule QtCore
17 \internal
18 \brief The QMetaObjectBuilder class supports building QMetaObject objects at runtime.
19
20*/
21
22/*!
23 \enum QMetaObjectBuilder::AddMember
24 This enum defines which members of QMetaObject should be copied by QMetaObjectBuilder::addMetaObject()
25
26 \value ClassName Add the class name.
27 \value SuperClass Add the super class.
28 \value Methods Add methods that aren't signals or slots.
29 \value Signals Add signals.
30 \value Slots Add slots.
31 \value Constructors Add constructors.
32 \value Properties Add properties.
33 \value Enumerators Add enumerators.
34 \value ClassInfos Add items of class information.
35 \value RelatedMetaObjects Add related meta objects.
36 \value StaticMetacall Add the static metacall function.
37 \value PublicMethods Add public methods (ignored for signals).
38 \value ProtectedMethods Add protected methods (ignored for signals).
39 \value PrivateMethods All private methods (ignored for signals).
40 \value AllMembers Add all members.
41 \value AllPrimaryMembers Add everything except the class name, super class, and static metacall function.
42*/
43
44static bool isBuiltinType(QByteArrayView type)
45{
46 int id = QMetaType::fromName(name: type).id();
47 if (!id && !type.isEmpty() && type != "void")
48 return false;
49 return (id < QMetaType::User);
50}
51
52// copied from qmetaobject.cpp
53[[maybe_unused]] static inline const QMetaObjectPrivate *qmobPriv(const uint* data)
54{ return reinterpret_cast<const QMetaObjectPrivate*>(data); }
55
56class QMetaMethodBuilderPrivate
57{
58public:
59 QMetaMethodBuilderPrivate
60 (QMetaMethod::MethodType _methodType,
61 const QByteArray& _signature,
62 const QByteArray& _returnType = QByteArray("void"),
63 QMetaMethod::Access _access = QMetaMethod::Public,
64 int _revision = 0)
65 : signature(QMetaObject::normalizedSignature(method: _signature.constData())),
66 returnType(QMetaObject::normalizedType(type: _returnType)),
67 attributes(((int)_access) | (((int)_methodType) << 2)),
68 revision(_revision)
69 {
70 Q_ASSERT((_methodType == QMetaMethod::Constructor) == returnType.isNull());
71 }
72
73 QByteArray signature;
74 QByteArray returnType;
75 QList<QByteArray> parameterNames;
76 QByteArray tag;
77 int attributes;
78 int revision;
79
80 QMetaMethod::MethodType methodType() const
81 {
82 return (QMetaMethod::MethodType)((attributes & MethodTypeMask) >> 2);
83 }
84
85 QMetaMethod::Access access() const
86 {
87 return (QMetaMethod::Access)(attributes & AccessMask);
88 }
89
90 void setAccess(QMetaMethod::Access value)
91 {
92 attributes = ((attributes & ~AccessMask) | (int)value);
93 }
94
95 QList<QByteArray> parameterTypes() const
96 {
97 return QMetaObjectPrivate::parameterTypeNamesFromSignature(sig: signature);
98 }
99
100 int parameterCount() const
101 {
102 return parameterTypes().size();
103 }
104
105 QByteArray name() const
106 {
107 return signature.left(n: qMax(a: signature.indexOf(c: '('), b: 0));
108 }
109};
110Q_DECLARE_TYPEINFO(QMetaMethodBuilderPrivate, Q_RELOCATABLE_TYPE);
111
112class QMetaPropertyBuilderPrivate
113{
114public:
115 QMetaPropertyBuilderPrivate
116 (const QByteArray& _name, const QByteArray& _type, QMetaType _metaType, int notifierIdx=-1,
117 int _revision = 0)
118 : name(_name),
119 type(QMetaObject::normalizedType(type: _type.constData())),
120 metaType(_metaType),
121 flags(Readable | Writable | Scriptable), notifySignal(notifierIdx),
122 revision(_revision)
123 {
124
125 }
126
127 QByteArray name;
128 QByteArray type;
129 QMetaType metaType;
130 int flags;
131 int notifySignal;
132 int revision;
133
134 bool flag(int f) const
135 {
136 return ((flags & f) != 0);
137 }
138
139 void setFlag(int f, bool value)
140 {
141 if (value)
142 flags |= f;
143 else
144 flags &= ~f;
145 }
146};
147Q_DECLARE_TYPEINFO(QMetaPropertyBuilderPrivate, Q_RELOCATABLE_TYPE);
148
149class QMetaEnumBuilderPrivate
150{
151public:
152 QMetaEnumBuilderPrivate(const QByteArray &_name)
153 : name(_name), enumName(_name)
154 {
155 }
156
157 QByteArray name;
158 QByteArray enumName;
159 QMetaType metaType;
160 QList<QByteArray> keys;
161 QList<quint64> values;
162 QFlags<EnumFlags> flags = {};
163
164 int addKey(const QByteArray &name, quint64 value)
165 {
166 int index = keys.size();
167 keys += name;
168 values += value;
169 return index;
170 }
171};
172Q_DECLARE_TYPEINFO(QMetaEnumBuilderPrivate, Q_RELOCATABLE_TYPE);
173
174class QMetaObjectBuilderPrivate
175{
176public:
177 QMetaObjectBuilderPrivate()
178 : flags(0)
179 {
180 superClass = &QObject::staticMetaObject;
181 staticMetacallFunction = nullptr;
182 }
183
184 QByteArray className;
185 const QMetaObject *superClass;
186 QMetaObjectBuilder::StaticMetacallFunction staticMetacallFunction;
187 std::vector<QMetaMethodBuilderPrivate> methods;
188 std::vector<QMetaMethodBuilderPrivate> constructors;
189 std::vector<QMetaPropertyBuilderPrivate> properties;
190 QList<QByteArray> classInfoNames;
191 QList<QByteArray> classInfoValues;
192 std::vector<QMetaEnumBuilderPrivate> enumerators;
193 QList<const QMetaObject *> relatedMetaObjects;
194 MetaObjectFlags flags;
195};
196
197/*!
198 Constructs a new QMetaObjectBuilder.
199*/
200QMetaObjectBuilder::QMetaObjectBuilder()
201{
202 d = new QMetaObjectBuilderPrivate();
203}
204
205/*!
206 Constructs a new QMetaObjectBuilder which is a copy of the
207 meta object information in \a prototype. Note: the super class
208 contents for \a prototype are not copied, only the immediate
209 class that is defined by \a prototype.
210
211 The \a members parameter indicates which members of \a prototype
212 should be added. The default is AllMembers.
213
214 \sa addMetaObject()
215*/
216QMetaObjectBuilder::QMetaObjectBuilder(const QMetaObject *prototype,
217 QMetaObjectBuilder::AddMembers members)
218{
219 d = new QMetaObjectBuilderPrivate();
220 addMetaObject(prototype, members);
221}
222
223/*!
224 Destroys this meta object builder.
225*/
226QMetaObjectBuilder::~QMetaObjectBuilder()
227{
228 delete d;
229}
230
231/*!
232 Returns the name of the class being constructed by this
233 meta object builder. The default value is an empty QByteArray.
234
235 \sa setClassName(), superClass()
236*/
237QByteArray QMetaObjectBuilder::className() const
238{
239 return d->className;
240}
241
242/*!
243 Sets the \a name of the class being constructed by this
244 meta object builder.
245
246 \sa className(), setSuperClass()
247*/
248void QMetaObjectBuilder::setClassName(const QByteArray &name)
249{
250 d->className = name;
251}
252
253/*!
254 Returns the superclass meta object of the class being constructed
255 by this meta object builder. The default value is the meta object
256 for QObject.
257
258 \sa setSuperClass(), className()
259*/
260const QMetaObject *QMetaObjectBuilder::superClass() const
261{
262 return d->superClass;
263}
264
265/*!
266 Sets the superclass meta object of the class being constructed
267 by this meta object builder to \a meta. The \a meta parameter
268 must not be null.
269
270 \sa superClass(), setClassName()
271*/
272void QMetaObjectBuilder::setSuperClass(const QMetaObject *meta)
273{
274 Q_ASSERT(meta);
275 d->superClass = meta;
276}
277
278/*!
279 Returns the flags of the class being constructed by this meta object
280 builder.
281
282 \sa setFlags()
283*/
284MetaObjectFlags QMetaObjectBuilder::flags() const
285{
286 return d->flags;
287}
288
289/*!
290 Sets the \a flags of the class being constructed by this meta object
291 builder.
292
293 \sa flags()
294*/
295void QMetaObjectBuilder::setFlags(MetaObjectFlags flags)
296{
297 d->flags = flags;
298}
299
300/*!
301 Returns the number of methods in this class, excluding the number
302 of methods in the base class. These include signals and slots
303 as well as normal member functions.
304
305 \sa addMethod(), method(), removeMethod(), indexOfMethod()
306*/
307int QMetaObjectBuilder::methodCount() const
308{
309 return int(d->methods.size());
310}
311
312/*!
313 Returns the number of constructors in this class.
314
315 \sa addConstructor(), constructor(), removeConstructor(), indexOfConstructor()
316*/
317int QMetaObjectBuilder::constructorCount() const
318{
319 return int(d->constructors.size());
320}
321
322/*!
323 Returns the number of properties in this class, excluding the number
324 of properties in the base class.
325
326 \sa addProperty(), property(), removeProperty(), indexOfProperty()
327*/
328int QMetaObjectBuilder::propertyCount() const
329{
330 return int(d->properties.size());
331}
332
333/*!
334 Returns the number of enumerators in this class, excluding the
335 number of enumerators in the base class.
336
337 \sa addEnumerator(), enumerator(), removeEnumerator()
338 \sa indexOfEnumerator()
339*/
340int QMetaObjectBuilder::enumeratorCount() const
341{
342 return int(d->enumerators.size());
343}
344
345/*!
346 Returns the number of items of class information in this class,
347 exclusing the number of items of class information in the base class.
348
349 \sa addClassInfo(), classInfoName(), classInfoValue(), removeClassInfo()
350 \sa indexOfClassInfo()
351*/
352int QMetaObjectBuilder::classInfoCount() const
353{
354 return d->classInfoNames.size();
355}
356
357/*!
358 Returns the number of related meta objects that are associated
359 with this class.
360
361 Related meta objects are used when resolving the enumerated type
362 associated with a property, where the enumerated type is in a
363 different class from the property.
364
365 \sa addRelatedMetaObject(), relatedMetaObject()
366 \sa removeRelatedMetaObject()
367*/
368int QMetaObjectBuilder::relatedMetaObjectCount() const
369{
370 return d->relatedMetaObjects.size();
371}
372
373/*!
374 Adds a new public method to this class with the specified \a signature.
375 Returns an object that can be used to adjust the other attributes
376 of the method. The \a signature will be normalized before it is
377 added to the class.
378
379 \sa method(), methodCount(), removeMethod(), indexOfMethod()
380*/
381QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QByteArray &signature)
382{
383 int index = int(d->methods.size());
384 d->methods.push_back(x: QMetaMethodBuilderPrivate(QMetaMethod::Method, signature));
385 return QMetaMethodBuilder(this, index);
386}
387
388/*!
389 Adds a new public method to this class with the specified
390 \a signature and \a returnType. Returns an object that can be
391 used to adjust the other attributes of the method. The \a signature
392 and \a returnType will be normalized before they are added to
393 the class.
394
395 \sa method(), methodCount(), removeMethod(), indexOfMethod()
396*/
397QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QByteArray &signature,
398 const QByteArray &returnType)
399{
400 int index = int(d->methods.size());
401 d->methods.push_back(x: QMetaMethodBuilderPrivate(QMetaMethod::Method, signature, returnType));
402 return QMetaMethodBuilder(this, index);
403}
404
405/*!
406 Adds a new public method to this class that has the same information as
407 \a prototype. This is used to clone the methods of an existing
408 QMetaObject. Returns an object that can be used to adjust the
409 attributes of the method.
410
411 This function will detect if \a prototype is an ordinary method,
412 signal, slot, or constructor and act accordingly.
413
414 \sa method(), methodCount(), removeMethod(), indexOfMethod()
415*/
416QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QMetaMethod &prototype)
417{
418 QMetaMethodBuilder method;
419 if (prototype.methodType() == QMetaMethod::Method)
420 method = addMethod(signature: prototype.methodSignature());
421 else if (prototype.methodType() == QMetaMethod::Signal)
422 method = addSignal(signature: prototype.methodSignature());
423 else if (prototype.methodType() == QMetaMethod::Slot)
424 method = addSlot(signature: prototype.methodSignature());
425 else if (prototype.methodType() == QMetaMethod::Constructor)
426 method = addConstructor(signature: prototype.methodSignature());
427 method.setReturnType(prototype.typeName());
428 method.setParameterNames(prototype.parameterNames());
429 method.setTag(prototype.tag());
430 method.setAccess(prototype.access());
431 method.setAttributes(prototype.attributes());
432 method.setRevision(prototype.revision());
433 method.setConst(prototype.isConst());
434 return method;
435}
436
437/*!
438 Adds a new public slot to this class with the specified \a signature.
439 Returns an object that can be used to adjust the other attributes
440 of the slot. The \a signature will be normalized before it is
441 added to the class.
442
443 \sa addMethod(), addSignal(), indexOfSlot()
444*/
445QMetaMethodBuilder QMetaObjectBuilder::addSlot(const QByteArray &signature)
446{
447 int index = int(d->methods.size());
448 d->methods.push_back(x: QMetaMethodBuilderPrivate(QMetaMethod::Slot, signature));
449 return QMetaMethodBuilder(this, index);
450}
451
452/*!
453 Adds a new signal to this class with the specified \a signature.
454 Returns an object that can be used to adjust the other attributes
455 of the signal. The \a signature will be normalized before it is
456 added to the class.
457
458 \sa addMethod(), addSlot(), indexOfSignal()
459*/
460QMetaMethodBuilder QMetaObjectBuilder::addSignal(const QByteArray &signature)
461{
462 int index = int(d->methods.size());
463 d->methods.push_back(x: QMetaMethodBuilderPrivate(QMetaMethod::Signal, signature,
464 QByteArray("void"), QMetaMethod::Public));
465 return QMetaMethodBuilder(this, index);
466}
467
468/*!
469 Adds a new constructor to this class with the specified \a signature.
470 Returns an object that can be used to adjust the other attributes
471 of the constructor. The \a signature will be normalized before it is
472 added to the class.
473
474 \sa constructor(), constructorCount(), removeConstructor()
475 \sa indexOfConstructor()
476*/
477QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QByteArray &signature)
478{
479 int index = int(d->constructors.size());
480 d->constructors.push_back(x: QMetaMethodBuilderPrivate(QMetaMethod::Constructor, signature,
481 /*returnType=*/QByteArray()));
482 return QMetaMethodBuilder(this, -(index + 1));
483}
484
485/*!
486 Adds a new constructor to this class that has the same information as
487 \a prototype. This is used to clone the constructors of an existing
488 QMetaObject. Returns an object that can be used to adjust the
489 attributes of the constructor.
490
491 This function requires that \a prototype be a constructor.
492
493 \sa constructor(), constructorCount(), removeConstructor()
494 \sa indexOfConstructor()
495*/
496QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QMetaMethod &prototype)
497{
498 Q_ASSERT(prototype.methodType() == QMetaMethod::Constructor);
499 QMetaMethodBuilder ctor = addConstructor(signature: prototype.methodSignature());
500 ctor.setReturnType(prototype.typeName());
501 ctor.setParameterNames(prototype.parameterNames());
502 ctor.setTag(prototype.tag());
503 ctor.setAccess(prototype.access());
504 ctor.setAttributes(prototype.attributes());
505 return ctor;
506}
507
508/*!
509 Adds a new readable/writable property to this class with the
510 specified \a name and \a type. Returns an object that can be used
511 to adjust the other attributes of the property. The \a type will
512 be normalized before it is added to the class. \a notifierId will
513 be registered as the property's \e notify signal.
514
515 \sa property(), propertyCount(), removeProperty(), indexOfProperty()
516*/
517QMetaPropertyBuilder QMetaObjectBuilder::addProperty(const QByteArray &name, const QByteArray &type,
518 int notifierId)
519{
520 return addProperty(name, type, metaType: QMetaType::fromName(name: type), notifierId);
521}
522
523/*!
524 \overload
525 */
526QMetaPropertyBuilder QMetaObjectBuilder::addProperty(const QByteArray &name, const QByteArray &type, QMetaType metaType, int notifierId)
527{
528 int index = int(d->properties.size());
529 d->properties.push_back(x: QMetaPropertyBuilderPrivate(name, type, metaType, notifierId));
530 return QMetaPropertyBuilder(this, index);
531}
532
533/*!
534 Adds a new property to this class that has the same information as
535 \a prototype. This is used to clone the properties of an existing
536 QMetaObject. Returns an object that can be used to adjust the
537 attributes of the property.
538
539 \sa property(), propertyCount(), removeProperty(), indexOfProperty()
540*/
541QMetaPropertyBuilder QMetaObjectBuilder::addProperty(const QMetaProperty &prototype)
542{
543 QMetaPropertyBuilder property = addProperty(name: prototype.name(), type: prototype.typeName(), metaType: prototype.metaType());
544 property.setReadable(prototype.isReadable());
545 property.setWritable(prototype.isWritable());
546 property.setResettable(prototype.isResettable());
547 property.setDesignable(prototype.isDesignable());
548 property.setScriptable(prototype.isScriptable());
549 property.setStored(prototype.isStored());
550 property.setUser(prototype.isUser());
551 property.setStdCppSet(prototype.hasStdCppSet());
552 property.setEnumOrFlag(prototype.isEnumType());
553 property.setConstant(prototype.isConstant());
554 property.setFinal(prototype.isFinal());
555 property.setRevision(prototype.revision());
556 if (prototype.hasNotifySignal()) {
557 // Find an existing method for the notify signal, or add a new one.
558 QMetaMethod method = prototype.notifySignal();
559 int index = indexOfMethod(signature: method.methodSignature());
560 if (index == -1)
561 index = addMethod(prototype: method).index();
562 d->properties[property._index].notifySignal = index;
563 }
564 return property;
565}
566
567/*!
568 Adds a new enumerator to this class with the specified
569 \a name. Returns an object that can be used to adjust
570 the other attributes of the enumerator.
571
572 \sa enumerator(), enumeratorCount(), removeEnumerator()
573 \sa indexOfEnumerator()
574*/
575QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QByteArray &name)
576{
577 int index = int(d->enumerators.size());
578 d->enumerators.push_back(x: QMetaEnumBuilderPrivate(name));
579 return QMetaEnumBuilder(this, index);
580}
581
582/*!
583 Adds a new enumerator to this class that has the same information as
584 \a prototype. This is used to clone the enumerators of an existing
585 QMetaObject. Returns an object that can be used to adjust the
586 attributes of the enumerator.
587
588 \sa enumerator(), enumeratorCount(), removeEnumerator()
589 \sa indexOfEnumerator()
590*/
591QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QMetaEnum &prototype)
592{
593 QMetaEnumBuilder en = addEnumerator(name: prototype.name());
594 en.setEnumName(prototype.enumName());
595 en.setMetaType(prototype.metaType());
596 en.setIsFlag(prototype.isFlag());
597 en.setIsScoped(prototype.isScoped());
598 int count = prototype.keyCount();
599 for (int index = 0; index < count; ++index)
600 en.addKey(name: prototype.key(index), value: prototype.value64(index).value_or(u: 0));
601 // reset the is64Bit() flag if necessary
602 en.setIs64Bit(prototype.is64Bit());
603 return en;
604}
605
606/*!
607 Adds \a name and \a value as an item of class information to this class.
608 Returns the index of the new item of class information.
609
610 \sa classInfoCount(), classInfoName(), classInfoValue(), removeClassInfo()
611 \sa indexOfClassInfo()
612*/
613int QMetaObjectBuilder::addClassInfo(const QByteArray &name, const QByteArray &value)
614{
615 int index = d->classInfoNames.size();
616 d->classInfoNames += name;
617 d->classInfoValues += value;
618 return index;
619}
620
621/*!
622 Adds \a meta to this class as a related meta object. Returns
623 the index of the new related meta object entry.
624
625 Related meta objects are used when resolving the enumerated type
626 associated with a property, where the enumerated type is in a
627 different class from the property.
628
629 \sa relatedMetaObjectCount(), relatedMetaObject()
630 \sa removeRelatedMetaObject()
631*/
632int QMetaObjectBuilder::addRelatedMetaObject(const QMetaObject *meta)
633{
634 Q_ASSERT(meta);
635 int index = d->relatedMetaObjects.size();
636 d->relatedMetaObjects.append(t: meta);
637 return index;
638}
639
640/*!
641 Adds the contents of \a prototype to this meta object builder.
642 This function is useful for cloning the contents of an existing QMetaObject.
643
644 The \a members parameter indicates which members of \a prototype
645 should be added. The default is AllMembers.
646*/
647void QMetaObjectBuilder::addMetaObject(const QMetaObject *prototype,
648 QMetaObjectBuilder::AddMembers members)
649{
650 Q_ASSERT(prototype);
651 int index;
652
653 if ((members & ClassName) != 0)
654 d->className = prototype->className();
655
656 if ((members & SuperClass) != 0)
657 d->superClass = prototype->superClass();
658
659 if ((members & (Methods | Signals | Slots)) != 0) {
660 for (index = prototype->methodOffset(); index < prototype->methodCount(); ++index) {
661 QMetaMethod method = prototype->method(index);
662 if (method.methodType() != QMetaMethod::Signal) {
663 if (method.access() == QMetaMethod::Public && (members & PublicMethods) == 0)
664 continue;
665 if (method.access() == QMetaMethod::Private && (members & PrivateMethods) == 0)
666 continue;
667 if (method.access() == QMetaMethod::Protected && (members & ProtectedMethods) == 0)
668 continue;
669 }
670 if (method.methodType() == QMetaMethod::Method && (members & Methods) != 0) {
671 addMethod(prototype: method);
672 } else if (method.methodType() == QMetaMethod::Signal &&
673 (members & Signals) != 0) {
674 addMethod(prototype: method);
675 } else if (method.methodType() == QMetaMethod::Slot &&
676 (members & Slots) != 0) {
677 addMethod(prototype: method);
678 }
679 }
680 }
681
682 if ((members & Constructors) != 0) {
683 for (index = 0; index < prototype->constructorCount(); ++index)
684 addConstructor(prototype: prototype->constructor(index));
685 }
686
687 if ((members & Properties) != 0) {
688 for (index = prototype->propertyOffset(); index < prototype->propertyCount(); ++index)
689 addProperty(prototype: prototype->property(index));
690 }
691
692 if ((members & Enumerators) != 0) {
693 for (index = prototype->enumeratorOffset(); index < prototype->enumeratorCount(); ++index)
694 addEnumerator(prototype: prototype->enumerator(index));
695 }
696
697 if ((members & ClassInfos) != 0) {
698 for (index = prototype->classInfoOffset(); index < prototype->classInfoCount(); ++index) {
699 QMetaClassInfo ci = prototype->classInfo(index);
700 addClassInfo(name: ci.name(), value: ci.value());
701 }
702 }
703
704 if ((members & RelatedMetaObjects) != 0) {
705 Q_ASSERT(qmobPriv(prototype->d.data)->revision >= 2);
706 const auto *objects = prototype->d.relatedMetaObjects;
707 if (objects) {
708 while (*objects != nullptr) {
709 addRelatedMetaObject(meta: *objects);
710 ++objects;
711 }
712 }
713 }
714
715 if ((members & StaticMetacall) != 0) {
716 Q_ASSERT(qmobPriv(prototype->d.data)->revision >= 6);
717 if (prototype->d.static_metacall)
718 setStaticMetacallFunction(prototype->d.static_metacall);
719 }
720}
721
722/*!
723 Returns the method at \a index in this class.
724
725 \sa methodCount(), addMethod(), removeMethod(), indexOfMethod()
726*/
727QMetaMethodBuilder QMetaObjectBuilder::method(int index) const
728{
729 if (uint(index) < d->methods.size())
730 return QMetaMethodBuilder(this, index);
731 else
732 return QMetaMethodBuilder();
733}
734
735/*!
736 Returns the constructor at \a index in this class.
737
738 \sa methodCount(), addMethod(), removeMethod(), indexOfConstructor()
739*/
740QMetaMethodBuilder QMetaObjectBuilder::constructor(int index) const
741{
742 if (uint(index) < d->constructors.size())
743 return QMetaMethodBuilder(this, -(index + 1));
744 else
745 return QMetaMethodBuilder();
746}
747
748/*!
749 Returns the property at \a index in this class.
750
751 \sa methodCount(), addMethod(), removeMethod(), indexOfProperty()
752*/
753QMetaPropertyBuilder QMetaObjectBuilder::property(int index) const
754{
755 if (uint(index) < d->properties.size())
756 return QMetaPropertyBuilder(this, index);
757 else
758 return QMetaPropertyBuilder();
759}
760
761/*!
762 Returns the enumerator at \a index in this class.
763
764 \sa enumeratorCount(), addEnumerator(), removeEnumerator()
765 \sa indexOfEnumerator()
766*/
767QMetaEnumBuilder QMetaObjectBuilder::enumerator(int index) const
768{
769 if (uint(index) < d->enumerators.size())
770 return QMetaEnumBuilder(this, index);
771 else
772 return QMetaEnumBuilder();
773}
774
775/*!
776 Returns the related meta object at \a index in this class.
777
778 Related meta objects are used when resolving the enumerated type
779 associated with a property, where the enumerated type is in a
780 different class from the property.
781
782 \sa relatedMetaObjectCount(), addRelatedMetaObject()
783 \sa removeRelatedMetaObject()
784*/
785const QMetaObject *QMetaObjectBuilder::relatedMetaObject(int index) const
786{
787 if (index >= 0 && index < d->relatedMetaObjects.size())
788 return d->relatedMetaObjects[index];
789 else
790 return nullptr;
791}
792
793/*!
794 Returns the name of the item of class information at \a index
795 in this class.
796
797 \sa classInfoCount(), addClassInfo(), classInfoValue(), removeClassInfo()
798 \sa indexOfClassInfo()
799*/
800QByteArray QMetaObjectBuilder::classInfoName(int index) const
801{
802 if (index >= 0 && index < d->classInfoNames.size())
803 return d->classInfoNames[index];
804 else
805 return QByteArray();
806}
807
808/*!
809 Returns the value of the item of class information at \a index
810 in this class.
811
812 \sa classInfoCount(), addClassInfo(), classInfoName(), removeClassInfo()
813 \sa indexOfClassInfo()
814*/
815QByteArray QMetaObjectBuilder::classInfoValue(int index) const
816{
817 if (index >= 0 && index < d->classInfoValues.size())
818 return d->classInfoValues[index];
819 else
820 return QByteArray();
821}
822
823/*!
824 Removes the method at \a index from this class. The indices of
825 all following methods will be adjusted downwards by 1. If the
826 method is registered as a notify signal on a property, then the
827 notify signal will be removed from the property.
828
829 \sa methodCount(), addMethod(), method(), indexOfMethod()
830*/
831void QMetaObjectBuilder::removeMethod(int index)
832{
833 if (uint(index) < d->methods.size()) {
834 d->methods.erase(position: d->methods.begin() + index);
835 for (auto &property : d->properties) {
836 // Adjust the indices of property notify signal references.
837 if (property.notifySignal == index) {
838 property.notifySignal = -1;
839 } else if (property.notifySignal > index)
840 property.notifySignal--;
841 }
842 }
843}
844
845/*!
846 Removes the constructor at \a index from this class. The indices of
847 all following constructors will be adjusted downwards by 1.
848
849 \sa constructorCount(), addConstructor(), constructor()
850 \sa indexOfConstructor()
851*/
852void QMetaObjectBuilder::removeConstructor(int index)
853{
854 if (uint(index) < d->constructors.size())
855 d->constructors.erase(position: d->constructors.begin() + index);
856}
857
858/*!
859 Removes the property at \a index from this class. The indices of
860 all following properties will be adjusted downwards by 1.
861
862 \sa propertyCount(), addProperty(), property(), indexOfProperty()
863*/
864void QMetaObjectBuilder::removeProperty(int index)
865{
866 if (uint(index) < d->properties.size())
867 d->properties.erase(position: d->properties.begin() + index);
868}
869
870/*!
871 Removes the enumerator at \a index from this class. The indices of
872 all following enumerators will be adjusted downwards by 1.
873
874 \sa enumertorCount(), addEnumerator(), enumerator()
875 \sa indexOfEnumerator()
876*/
877void QMetaObjectBuilder::removeEnumerator(int index)
878{
879 if (uint(index) < d->enumerators.size())
880 d->enumerators.erase(position: d->enumerators.begin() + index);
881}
882
883/*!
884 Removes the item of class information at \a index from this class.
885 The indices of all following items will be adjusted downwards by 1.
886
887 \sa classInfoCount(), addClassInfo(), classInfoName(), classInfoValue()
888 \sa indexOfClassInfo()
889*/
890void QMetaObjectBuilder::removeClassInfo(int index)
891{
892 if (index >= 0 && index < d->classInfoNames.size()) {
893 d->classInfoNames.removeAt(i: index);
894 d->classInfoValues.removeAt(i: index);
895 }
896}
897
898/*!
899 Removes the related meta object at \a index from this class.
900 The indices of all following related meta objects will be adjusted
901 downwards by 1.
902
903 Related meta objects are used when resolving the enumerated type
904 associated with a property, where the enumerated type is in a
905 different class from the property.
906
907 \sa relatedMetaObjectCount(), addRelatedMetaObject()
908 \sa relatedMetaObject()
909*/
910void QMetaObjectBuilder::removeRelatedMetaObject(int index)
911{
912 if (index >= 0 && index < d->relatedMetaObjects.size())
913 d->relatedMetaObjects.removeAt(i: index);
914}
915
916/*!
917 Finds a method with the specified \a signature and returns its index;
918 otherwise returns -1. The \a signature will be normalized by this method.
919
920 \sa method(), methodCount(), addMethod(), removeMethod()
921*/
922int QMetaObjectBuilder::indexOfMethod(const QByteArray &signature)
923{
924 QByteArray sig = QMetaObject::normalizedSignature(method: signature);
925 for (const auto &method : d->methods) {
926 if (sig == method.signature)
927 return int(&method - &d->methods.front());
928 }
929 return -1;
930}
931
932/*!
933 Finds a signal with the specified \a signature and returns its index;
934 otherwise returns -1. The \a signature will be normalized by this method.
935
936 \sa indexOfMethod(), indexOfSlot()
937*/
938int QMetaObjectBuilder::indexOfSignal(const QByteArray &signature)
939{
940 QByteArray sig = QMetaObject::normalizedSignature(method: signature);
941 for (const auto &method : d->methods) {
942 if (method.methodType() == QMetaMethod::Signal && sig == method.signature)
943 return int(&method - &d->methods.front());
944 }
945 return -1;
946}
947
948/*!
949 Finds a slot with the specified \a signature and returns its index;
950 otherwise returns -1. The \a signature will be normalized by this method.
951
952 \sa indexOfMethod(), indexOfSignal()
953*/
954int QMetaObjectBuilder::indexOfSlot(const QByteArray &signature)
955{
956 QByteArray sig = QMetaObject::normalizedSignature(method: signature);
957 for (const auto &method : d->methods) {
958 if (method.methodType() == QMetaMethod::Slot && sig == method.signature)
959 return int(&method - &d->methods.front());
960 }
961 return -1;
962}
963
964/*!
965 Finds a constructor with the specified \a signature and returns its index;
966 otherwise returns -1. The \a signature will be normalized by this method.
967
968 \sa constructor(), constructorCount(), addConstructor(), removeConstructor()
969*/
970int QMetaObjectBuilder::indexOfConstructor(const QByteArray &signature)
971{
972 QByteArray sig = QMetaObject::normalizedSignature(method: signature);
973 for (const auto &constructor : d->constructors) {
974 if (sig == constructor.signature)
975 return int(&constructor - &d->constructors.front());
976 }
977 return -1;
978}
979
980/*!
981 Finds a property with the specified \a name and returns its index;
982 otherwise returns -1.
983
984 \sa property(), propertyCount(), addProperty(), removeProperty()
985*/
986int QMetaObjectBuilder::indexOfProperty(const QByteArray &name)
987{
988 for (const auto &property : d->properties) {
989 if (name == property.name)
990 return int(&property - &d->properties.front());
991 }
992 return -1;
993}
994
995/*!
996 Finds an enumerator with the specified \a name and returns its index;
997 otherwise returns -1.
998
999 \sa enumertor(), enumeratorCount(), addEnumerator(), removeEnumerator()
1000*/
1001int QMetaObjectBuilder::indexOfEnumerator(const QByteArray &name)
1002{
1003 for (const auto &enumerator : d->enumerators) {
1004 if (name == enumerator.name)
1005 return int(&enumerator - &d->enumerators.front());
1006 }
1007 return -1;
1008}
1009
1010/*!
1011 Finds an item of class information with the specified \a name and
1012 returns its index; otherwise returns -1.
1013
1014 \sa classInfoName(), classInfoValue(), classInfoCount(), addClassInfo()
1015 \sa removeClassInfo()
1016*/
1017int QMetaObjectBuilder::indexOfClassInfo(const QByteArray &name)
1018{
1019 for (int index = 0; index < d->classInfoNames.size(); ++index) {
1020 if (name == d->classInfoNames[index])
1021 return index;
1022 }
1023 return -1;
1024}
1025
1026// Align on a specific type boundary.
1027#ifdef ALIGN
1028# undef ALIGN
1029#endif
1030#define ALIGN(size,type) \
1031 (size) = ((size) + sizeof(type) - 1) & ~(sizeof(type) - 1)
1032
1033/*!
1034 \class QMetaStringTable
1035 \inmodule QtCore
1036 \internal
1037 \brief The QMetaStringTable class can generate a meta-object string table at runtime.
1038*/
1039
1040QMetaStringTable::QMetaStringTable(const QByteArray &className)
1041 : m_index(0)
1042 , m_className(className)
1043{
1044 const int index = enter(value: m_className);
1045 Q_ASSERT(index == 0);
1046 Q_UNUSED(index);
1047}
1048
1049// Enters the given value into the string table (if it hasn't already been
1050// entered). Returns the index of the string.
1051int QMetaStringTable::enter(const QByteArray &value)
1052{
1053 Entries::iterator it = m_entries.find(key: value);
1054 if (it != m_entries.end())
1055 return it.value();
1056 int pos = m_index;
1057 m_entries.insert(key: value, value: pos);
1058 ++m_index;
1059 return pos;
1060}
1061
1062int QMetaStringTable::preferredAlignment()
1063{
1064 return alignof(uint);
1065}
1066
1067// Returns the size (in bytes) required for serializing this string table.
1068int QMetaStringTable::blobSize() const
1069{
1070 int size = int(m_entries.size() * 2 * sizeof(uint));
1071 Entries::const_iterator it;
1072 for (it = m_entries.constBegin(); it != m_entries.constEnd(); ++it)
1073 size += it.key().size() + 1;
1074 return size;
1075}
1076
1077static void writeString(char *out, int i, const QByteArray &str,
1078 const int offsetOfStringdataMember, int &stringdataOffset)
1079{
1080 int size = str.size();
1081 int offset = offsetOfStringdataMember + stringdataOffset;
1082 uint offsetLen[2] = { uint(offset), uint(size) };
1083
1084 memcpy(dest: out + 2 * i * sizeof(uint), src: &offsetLen, n: 2 * sizeof(uint));
1085
1086 memcpy(dest: out + offset, src: str.constData(), n: size);
1087 out[offset + size] = '\0';
1088
1089 stringdataOffset += size + 1;
1090}
1091
1092// Writes strings to string data struct.
1093// The struct consists of an array of QByteArrayData, followed by a char array
1094// containing the actual strings. This format must match the one produced by
1095// moc (see generator.cpp).
1096void QMetaStringTable::writeBlob(char *out) const
1097{
1098 Q_ASSERT(!(reinterpret_cast<quintptr>(out) & (preferredAlignment() - 1)));
1099
1100 int offsetOfStringdataMember = int(m_entries.size() * 2 * sizeof(uint));
1101 int stringdataOffset = 0;
1102
1103 // qt_metacast expects the first string in the string table to be the class name.
1104 writeString(out, /*index*/ i: 0, str: m_className, offsetOfStringdataMember, stringdataOffset);
1105
1106 for (Entries::ConstIterator it = m_entries.constBegin(), end = m_entries.constEnd();
1107 it != end; ++it) {
1108 const int i = it.value();
1109 if (i == 0)
1110 continue;
1111 const QByteArray &str = it.key();
1112
1113 writeString(out, i, str, offsetOfStringdataMember, stringdataOffset);
1114 }
1115}
1116
1117// Returns the number of integers needed to store these methods' parameter type
1118// infos or type names, parameter names and, if present, the method revision.
1119// This is needed for calculating the size of the methods' parameter type/name
1120// meta-data.
1121static int aggregateParameterCount(const std::vector<QMetaMethodBuilderPrivate> &methods)
1122{
1123 int sum = 0;
1124 for (const auto &method : methods) {
1125 if (method.revision)
1126 ++sum;
1127
1128 // type infos or type names; +1 for return type (constructors don't
1129 // have one, so this stores a link to an empty string)
1130 sum += method.parameterCount() + 1;
1131
1132 // parameter names (return type doesn't get one)
1133 sum += method.parameterCount();
1134 }
1135 return sum;
1136}
1137
1138enum Mode {
1139 Prepare, // compute the size of the metaobject
1140 Construct // construct metaobject in pre-allocated buffer
1141};
1142// Build a QMetaObject in "buf" based on the information in "d".
1143// If the mode is prepare, then return the number of bytes needed to
1144// build the QMetaObject.
1145template<Mode mode>
1146static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
1147 int expectedSize)
1148{
1149 Q_UNUSED(expectedSize); // Avoid warning in release mode
1150 Q_UNUSED(buf);
1151 qsizetype size = 0;
1152 int dataIndex;
1153 int paramsIndex;
1154 int enumIndex;
1155 int index;
1156
1157 // Create the main QMetaObject structure at the start of the buffer.
1158 QMetaObject *meta = reinterpret_cast<QMetaObject *>(buf);
1159 size += sizeof(QMetaObject);
1160 ALIGN(size, int);
1161 if constexpr (mode == Construct) {
1162 meta->d.superdata = d->superClass;
1163 meta->d.relatedMetaObjects = nullptr;
1164 meta->d.extradata = nullptr;
1165 meta->d.metaTypes = nullptr;
1166 meta->d.static_metacall = d->staticMetacallFunction;
1167 }
1168
1169 // Populate the QMetaObjectPrivate structure.
1170 QMetaObjectPrivate *pmeta = buf ? reinterpret_cast<QMetaObjectPrivate *>(buf + size)
1171 : nullptr;
1172 //int pmetaSize = size;
1173 dataIndex = MetaObjectPrivateFieldCount;
1174 int methodParametersDataSize = aggregateParameterCount(methods: d->methods)
1175 + aggregateParameterCount(methods: d->constructors);
1176 if constexpr (mode == Construct) {
1177 static_assert(QMetaObjectPrivate::OutputRevision == 13, "QMetaObjectBuilder should generate the same version as moc");
1178 pmeta->revision = QMetaObjectPrivate::OutputRevision;
1179 pmeta->flags = d->flags.toInt() | AllocatedMetaObject;
1180 pmeta->className = 0; // Class name is always the first string.
1181 //pmeta->signalCount is handled in the "output method loop" as an optimization.
1182
1183 pmeta->classInfoCount = d->classInfoNames.size();
1184 pmeta->classInfoData = dataIndex;
1185 dataIndex += 2 * d->classInfoNames.size();
1186
1187 pmeta->methodCount = int(d->methods.size());
1188 pmeta->methodData = dataIndex;
1189 dataIndex += QMetaObjectPrivate::IntsPerMethod * int(d->methods.size());
1190 paramsIndex = dataIndex;
1191 dataIndex += methodParametersDataSize;
1192
1193 pmeta->propertyCount = int(d->properties.size());
1194 pmeta->propertyData = dataIndex;
1195 dataIndex += QMetaObjectPrivate::IntsPerProperty * int(d->properties.size());
1196
1197 pmeta->enumeratorCount = int(d->enumerators.size());
1198 pmeta->enumeratorData = dataIndex;
1199 dataIndex += QMetaObjectPrivate::IntsPerEnum * int(d->enumerators.size());
1200
1201 pmeta->constructorCount = int(d->constructors.size());
1202 pmeta->constructorData = dataIndex;
1203 dataIndex += QMetaObjectPrivate::IntsPerMethod * int(d->constructors.size());
1204 } else {
1205 dataIndex += 2 * int(d->classInfoNames.size());
1206 dataIndex += QMetaObjectPrivate::IntsPerMethod * int(d->methods.size());
1207 paramsIndex = dataIndex;
1208 dataIndex += methodParametersDataSize;
1209 dataIndex += QMetaObjectPrivate::IntsPerProperty * int(d->properties.size());
1210 dataIndex += QMetaObjectPrivate::IntsPerEnum * int(d->enumerators.size());
1211 dataIndex += QMetaObjectPrivate::IntsPerMethod * int(d->constructors.size());
1212 }
1213
1214 // Allocate space for the enumerator key names and values.
1215 enumIndex = dataIndex;
1216 for (const auto &enumerator : d->enumerators) {
1217 dataIndex += 2 * enumerator.keys.size();
1218 if (enumerator.flags & EnumIs64Bit)
1219 dataIndex += enumerator.keys.size();
1220 }
1221
1222 // Zero terminator at the end of the data offset table.
1223 ++dataIndex;
1224
1225 // Find the start of the data and string tables.
1226 int *data = reinterpret_cast<int *>(pmeta);
1227 size += dataIndex * sizeof(int);
1228 ALIGN(size, void *);
1229 [[maybe_unused]] char *str = reinterpret_cast<char *>(buf + size);
1230 if constexpr (mode == Construct) {
1231 meta->d.stringdata = reinterpret_cast<const uint *>(str);
1232 meta->d.data = reinterpret_cast<uint *>(data);
1233 }
1234
1235 // Reset the current data position to just past the QMetaObjectPrivate.
1236 dataIndex = MetaObjectPrivateFieldCount;
1237
1238 QMetaStringTable strings(d->className);
1239
1240 // Output the class infos,
1241 Q_ASSERT(!buf || dataIndex == pmeta->classInfoData);
1242 for (index = 0; index < d->classInfoNames.size(); ++index) {
1243 [[maybe_unused]] int name = strings.enter(value: d->classInfoNames[index]);
1244 [[maybe_unused]] int value = strings.enter(value: d->classInfoValues[index]);
1245 if constexpr (mode == Construct) {
1246 data[dataIndex] = name;
1247 data[dataIndex + 1] = value;
1248 }
1249 dataIndex += 2;
1250 }
1251
1252 // Output the methods in the class.
1253 Q_ASSERT(!buf || dataIndex == pmeta->methodData);
1254 // property count + enum count + 1 for metatype of this metaobject
1255 int parameterMetaTypesIndex = int(d->properties.size()) + int(d->enumerators.size()) + 1;
1256 for (const auto &method : d->methods) {
1257 [[maybe_unused]] int name = strings.enter(value: method.name());
1258 int argc = method.parameterCount();
1259 [[maybe_unused]] int tag = strings.enter(value: method.tag);
1260 [[maybe_unused]] int attrs = method.attributes;
1261 if (method.revision)
1262 ++paramsIndex;
1263 if constexpr (mode == Construct) {
1264 data[dataIndex] = name;
1265 data[dataIndex + 1] = argc;
1266 data[dataIndex + 2] = paramsIndex;
1267 data[dataIndex + 3] = tag;
1268 data[dataIndex + 4] = attrs;
1269 data[dataIndex + 5] = parameterMetaTypesIndex;
1270 if (method.methodType() == QMetaMethod::Signal)
1271 pmeta->signalCount++;
1272 }
1273 dataIndex += QMetaObjectPrivate::IntsPerMethod;
1274 paramsIndex += 1 + argc * 2;
1275 parameterMetaTypesIndex += 1 + argc;
1276 }
1277
1278 // Output the method parameters in the class.
1279 Q_ASSERT(!buf || dataIndex == pmeta->methodData + int(d->methods.size()) * QMetaObjectPrivate::IntsPerMethod);
1280 for (int x = 0; x < 2; ++x) {
1281 const std::vector<QMetaMethodBuilderPrivate> &methods = (x == 0) ? d->methods : d->constructors;
1282 for (const auto &method : methods) {
1283 if (method.revision) {
1284 if constexpr (mode == Construct)
1285 data[dataIndex] = method.revision;
1286 ++dataIndex;
1287 }
1288
1289 const QList<QByteArray> paramTypeNames = method.parameterTypes();
1290 int paramCount = paramTypeNames.size();
1291 for (int i = -1; i < paramCount; ++i) {
1292 const QByteArray &typeName = (i < 0) ? method.returnType : paramTypeNames.at(i);
1293 [[maybe_unused]] int typeInfo;
1294 if (isBuiltinType(type: typeName))
1295 typeInfo = QMetaType::fromName(name: typeName).id();
1296 else
1297 typeInfo = IsUnresolvedType | strings.enter(value: typeName);
1298 if constexpr (mode == Construct)
1299 data[dataIndex] = typeInfo;
1300 ++dataIndex;
1301 }
1302
1303 QList<QByteArray> paramNames = method.parameterNames;
1304 while (paramNames.size() < paramCount)
1305 paramNames.append(t: QByteArray());
1306 for (int i = 0; i < paramCount; ++i) {
1307 [[maybe_unused]] int stringIndex = strings.enter(value: paramNames.at(i));
1308 if constexpr (mode == Construct)
1309 data[dataIndex] = stringIndex;
1310 ++dataIndex;
1311 }
1312 }
1313 }
1314
1315 // Output the properties in the class.
1316 Q_ASSERT(!buf || dataIndex == pmeta->propertyData);
1317 for (QMetaPropertyBuilderPrivate &prop : d->properties) {
1318 [[maybe_unused]] int name = strings.enter(value: prop.name);
1319
1320 // try to resolve the metatype again if it was unknown
1321 if (!prop.metaType.isValid())
1322 prop.metaType = QMetaType::fromName(name: prop.type);
1323 [[maybe_unused]] const int typeInfo = prop.metaType.isValid()
1324 ? prop.metaType.id()
1325 : IsUnresolvedType | strings.enter(value: prop.type);
1326
1327 [[maybe_unused]] int flags = prop.flags;
1328
1329 if (isBuiltinType(type: prop.type))
1330 flags |= EnumOrFlag;
1331
1332 if constexpr (mode == Construct) {
1333 data[dataIndex] = name;
1334 data[dataIndex + 1] = typeInfo;
1335 data[dataIndex + 2] = flags;
1336 data[dataIndex + 3] = prop.notifySignal;
1337 data[dataIndex + 4] = prop.revision;
1338 }
1339 dataIndex += QMetaObjectPrivate::IntsPerProperty;
1340 }
1341
1342 // Output the enumerators in the class.
1343 Q_ASSERT(!buf || dataIndex == pmeta->enumeratorData);
1344 for (const auto &enumerator : d->enumerators) {
1345 [[maybe_unused]] int name = strings.enter(value: enumerator.name);
1346 [[maybe_unused]] int enumName = strings.enter(value: enumerator.enumName);
1347 int count = enumerator.keys.size();
1348 if constexpr (mode == Construct) {
1349 data[dataIndex] = name;
1350 data[dataIndex + 1] = enumName;
1351 data[dataIndex + 2] = enumerator.flags.toInt();
1352 data[dataIndex + 3] = count;
1353 data[dataIndex + 4] = enumIndex;
1354 }
1355 for (int key = 0; key < count; ++key) {
1356 [[maybe_unused]] int keyIndex = strings.enter(value: enumerator.keys[key]);
1357 if constexpr (mode == Construct) {
1358 data[enumIndex + 0] = keyIndex;
1359 data[enumIndex + 1] = uint(enumerator.values[key]);
1360 }
1361 enumIndex += 2;
1362 }
1363 bool is64Bit = enumerator.flags.testAnyFlags(flags: EnumIs64Bit);
1364 for (int key = 0; is64Bit && key < count; ++key) {
1365 if constexpr (mode == Construct) {
1366 data[enumIndex] = uint(enumerator.values[key] >> 32);
1367 }
1368 ++enumIndex;
1369 }
1370 dataIndex += QMetaObjectPrivate::IntsPerEnum;
1371 }
1372
1373 // Output the constructors in the class.
1374 Q_ASSERT(!buf || dataIndex == pmeta->constructorData);
1375 for (const auto &ctor : d->constructors) {
1376 [[maybe_unused]] int name = strings.enter(value: ctor.name());
1377 int argc = ctor.parameterCount();
1378 [[maybe_unused]] int tag = strings.enter(value: ctor.tag);
1379 [[maybe_unused]] int attrs = ctor.attributes;
1380 if constexpr (mode == Construct) {
1381 data[dataIndex] = name;
1382 data[dataIndex + 1] = argc;
1383 data[dataIndex + 2] = paramsIndex;
1384 data[dataIndex + 3] = tag;
1385 data[dataIndex + 4] = attrs;
1386 data[dataIndex + 5] = parameterMetaTypesIndex;
1387 }
1388 dataIndex += QMetaObjectPrivate::IntsPerMethod;
1389 paramsIndex += 1 + argc * 2;
1390 if (ctor.revision)
1391 ++paramsIndex;
1392 parameterMetaTypesIndex += argc;
1393 }
1394
1395 size += strings.blobSize();
1396
1397 if constexpr (mode == Construct)
1398 strings.writeBlob(out: str);
1399
1400 // Output the zero terminator in the data array.
1401 if constexpr (mode == Construct)
1402 data[enumIndex] = 0;
1403
1404 // Create the relatedMetaObjects block if we need one.
1405 if (d->relatedMetaObjects.size() > 0) {
1406 using SuperData = QMetaObject::SuperData;
1407 ALIGN(size, SuperData);
1408 auto objects = reinterpret_cast<SuperData *>(buf + size);
1409 if constexpr (mode == Construct) {
1410 meta->d.relatedMetaObjects = objects;
1411 for (index = 0; index < d->relatedMetaObjects.size(); ++index)
1412 objects[index] = d->relatedMetaObjects[index];
1413 objects[index] = nullptr;
1414 }
1415 size += sizeof(SuperData) * (d->relatedMetaObjects.size() + 1);
1416 }
1417
1418 ALIGN(size, QtPrivate::QMetaTypeInterface *);
1419 auto types = reinterpret_cast<const QtPrivate::QMetaTypeInterface **>(buf + size);
1420 if constexpr (mode == Construct) {
1421 meta->d.metaTypes = types;
1422 for (const auto &prop : d->properties) {
1423 QMetaType mt = prop.metaType;
1424 *types = mt.iface();
1425 types++;
1426 }
1427 // add metatypes for enumerators
1428 for (const auto &enumerator: d->enumerators) {
1429 QMetaType mt = enumerator.metaType;
1430 mt.registerType();
1431 *types = mt.iface();
1432 types++;
1433 }
1434 // add metatype interface for this metaobject - must be null
1435 // as we can't know our metatype
1436 *types = nullptr;
1437 types++;
1438 for (const auto &method: d->methods) {
1439 QMetaType mt(QMetaType::fromName(name: method.returnType).id());
1440 *types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt);
1441 types++;
1442 for (const auto &parameterType: method.parameterTypes()) {
1443 QMetaType mt = QMetaType::fromName(name: parameterType);
1444 *types = mt.iface();
1445 types++;
1446 }
1447 }
1448 for (const auto &constructor : d->constructors) {
1449 for (const auto &parameterType : constructor.parameterTypes()) {
1450 QMetaType mt = QMetaType::fromName(name: parameterType);
1451 *types = mt.iface();
1452 types++;
1453 }
1454 }
1455 }
1456 // parameterMetaTypesIndex is equal to the total number of metatypes
1457 size += sizeof(QMetaType) * parameterMetaTypesIndex;
1458
1459 // Align the final size and return it.
1460 ALIGN(size, void *);
1461 Q_ASSERT(!buf || size == expectedSize);
1462 return size;
1463}
1464
1465/*!
1466 Converts this meta object builder into a concrete QMetaObject.
1467 The return value should be deallocated using free() once it
1468 is no longer needed.
1469
1470 The returned meta object is a snapshot of the state of the
1471 QMetaObjectBuilder. Any further modifications to the QMetaObjectBuilder
1472 will not be reflected in previous meta objects returned by
1473 this method.
1474*/
1475QMetaObject *QMetaObjectBuilder::toMetaObject() const
1476{
1477 int size = buildMetaObject<Prepare>(d, buf: nullptr, expectedSize: 0);
1478 char *buf = new (calloc(nmemb: size, size: 1)) char[size];
1479 buildMetaObject<Construct>(d, buf, expectedSize: size);
1480 return reinterpret_cast<QMetaObject *>(buf);
1481}
1482
1483/*!
1484 \typedef QMetaObjectBuilder::StaticMetacallFunction
1485
1486 Typedef for static metacall functions. The three parameters are
1487 the call type value, the constructor index, and the
1488 array of parameters.
1489*/
1490
1491/*!
1492 Returns the static metacall function to use to construct objects
1493 of this class. The default value is null.
1494
1495 \sa setStaticMetacallFunction()
1496*/
1497QMetaObjectBuilder::StaticMetacallFunction QMetaObjectBuilder::staticMetacallFunction() const
1498{
1499 return d->staticMetacallFunction;
1500}
1501
1502/*!
1503 Sets the static metacall function to use to construct objects
1504 of this class to \a value. The default value is null.
1505
1506 \sa staticMetacallFunction()
1507*/
1508void QMetaObjectBuilder::setStaticMetacallFunction
1509 (QMetaObjectBuilder::StaticMetacallFunction value)
1510{
1511 d->staticMetacallFunction = value;
1512}
1513
1514/*!
1515 \class QMetaMethodBuilder
1516 \inmodule QtCore
1517 \internal
1518 \brief The QMetaMethodBuilder class enables modifications to a method definition on a meta object builder.
1519*/
1520
1521QMetaMethodBuilderPrivate *QMetaMethodBuilder::d_func() const
1522{
1523 // Positive indices indicate methods, negative indices indicate constructors.
1524 if (_mobj && _index >= 0 && _index < int(_mobj->d->methods.size()))
1525 return &(_mobj->d->methods[_index]);
1526 else if (_mobj && -_index >= 1 && -_index <= int(_mobj->d->constructors.size()))
1527 return &(_mobj->d->constructors[(-_index) - 1]);
1528 else
1529 return nullptr;
1530}
1531
1532/*!
1533 \fn QMetaMethodBuilder::QMetaMethodBuilder()
1534 \internal
1535*/
1536
1537/*!
1538 Returns the index of this method within its QMetaObjectBuilder.
1539*/
1540int QMetaMethodBuilder::index() const
1541{
1542 if (_index >= 0)
1543 return _index; // Method, signal, or slot
1544 else
1545 return (-_index) - 1; // Constructor
1546}
1547
1548/*!
1549 Returns the type of this method (signal, slot, method, or constructor).
1550*/
1551QMetaMethod::MethodType QMetaMethodBuilder::methodType() const
1552{
1553 QMetaMethodBuilderPrivate *d = d_func();
1554 if (d)
1555 return d->methodType();
1556 else
1557 return QMetaMethod::Method;
1558}
1559
1560/*!
1561 Returns the signature of this method.
1562
1563 \sa parameterNames(), returnType()
1564*/
1565QByteArray QMetaMethodBuilder::signature() const
1566{
1567 QMetaMethodBuilderPrivate *d = d_func();
1568 if (d)
1569 return d->signature;
1570 else
1571 return QByteArray();
1572}
1573
1574/*!
1575 Returns the return type for this method; empty if the method's
1576 return type is \c{void}.
1577
1578 \sa setReturnType(), signature()
1579*/
1580QByteArray QMetaMethodBuilder::returnType() const
1581{
1582 QMetaMethodBuilderPrivate *d = d_func();
1583 if (d)
1584 return d->returnType;
1585 else
1586 return QByteArray();
1587}
1588
1589/*!
1590 Sets the return type for this method to \a value. If \a value
1591 is empty, then the method's return type is \c{void}. The \a value
1592 will be normalized before it is added to the method.
1593
1594 \sa returnType(), parameterTypes(), signature()
1595*/
1596void QMetaMethodBuilder::setReturnType(const QByteArray &value)
1597{
1598 QMetaMethodBuilderPrivate *d = d_func();
1599 if (d)
1600 d->returnType = QMetaObject::normalizedType(type: value);
1601}
1602
1603/*!
1604 Returns the list of parameter types for this method.
1605
1606 \sa returnType(), parameterNames()
1607*/
1608QList<QByteArray> QMetaMethodBuilder::parameterTypes() const
1609{
1610 QMetaMethodBuilderPrivate *d = d_func();
1611 if (d)
1612 return d->parameterTypes();
1613 else
1614 return QList<QByteArray>();
1615}
1616
1617/*!
1618 Returns the list of parameter names for this method.
1619
1620 \sa setParameterNames()
1621*/
1622QList<QByteArray> QMetaMethodBuilder::parameterNames() const
1623{
1624 QMetaMethodBuilderPrivate *d = d_func();
1625 if (d)
1626 return d->parameterNames;
1627 else
1628 return QList<QByteArray>();
1629}
1630
1631/*!
1632 Sets the list of parameter names for this method to \a value.
1633
1634 \sa parameterNames()
1635*/
1636void QMetaMethodBuilder::setParameterNames(const QList<QByteArray> &value)
1637{
1638 QMetaMethodBuilderPrivate *d = d_func();
1639 Q_ASSERT(d->parameterCount() >= value.size());
1640 if (d)
1641 d->parameterNames = value;
1642}
1643
1644/*!
1645 Returns the tag associated with this method.
1646
1647 \sa setTag()
1648*/
1649QByteArray QMetaMethodBuilder::tag() const
1650{
1651 QMetaMethodBuilderPrivate *d = d_func();
1652 if (d)
1653 return d->tag;
1654 else
1655 return QByteArray();
1656}
1657
1658/*!
1659 Sets the tag associated with this method to \a value.
1660
1661 \sa setTag()
1662*/
1663void QMetaMethodBuilder::setTag(const QByteArray &value)
1664{
1665 QMetaMethodBuilderPrivate *d = d_func();
1666 if (d)
1667 d->tag = value;
1668}
1669
1670/*!
1671 Returns the access specification of this method (private, protected,
1672 or public). The default value is QMetaMethod::Public for methods,
1673 slots, signals and constructors.
1674
1675 \sa setAccess()
1676*/
1677QMetaMethod::Access QMetaMethodBuilder::access() const
1678{
1679 QMetaMethodBuilderPrivate *d = d_func();
1680 if (d)
1681 return d->access();
1682 else
1683 return QMetaMethod::Public;
1684}
1685
1686/*!
1687 Sets the access specification of this method (private, protected,
1688 or public) to \a value. If the method is a signal, this function
1689 will be ignored.
1690
1691 \sa access()
1692*/
1693void QMetaMethodBuilder::setAccess(QMetaMethod::Access value)
1694{
1695 QMetaMethodBuilderPrivate *d = d_func();
1696 if (d && d->methodType() != QMetaMethod::Signal)
1697 d->setAccess(value);
1698}
1699
1700/*!
1701 Returns the additional attributes for this method.
1702
1703 \sa setAttributes()
1704*/
1705int QMetaMethodBuilder::attributes() const
1706{
1707 QMetaMethodBuilderPrivate *d = d_func();
1708 if (d)
1709 return (d->attributes >> 4) & 0x7;
1710 else
1711 return 0;
1712}
1713
1714/*!
1715 Sets the additional attributes for this method to \a value.
1716
1717 \sa attributes()
1718*/
1719void QMetaMethodBuilder::setAttributes(int value)
1720{
1721 QMetaMethodBuilderPrivate *d = d_func();
1722 if (d) {
1723 d->attributes &= ~0x70;
1724 d->attributes |= (value & 0x7) << 4;
1725 }
1726}
1727
1728/*!
1729 Returns true if the method is const qualified.
1730 */
1731bool QMetaMethodBuilder::isConst() const
1732{
1733 QMetaMethodBuilderPrivate *d = d_func();
1734 if (!d)
1735 return false;
1736 return (d->attributes & MethodIsConst);
1737}
1738
1739void QMetaMethodBuilder::setConst(bool methodIsConst)
1740{
1741 QMetaMethodBuilderPrivate *d = d_func();
1742 if (!d)
1743 return;
1744 if (methodIsConst)
1745 d->attributes |= MethodIsConst;
1746 else
1747 d->attributes &= ~MethodIsConst;
1748}
1749
1750/*!
1751 Returns the revision of this method.
1752
1753 \sa setRevision()
1754*/
1755int QMetaMethodBuilder::revision() const
1756{
1757 QMetaMethodBuilderPrivate *d = d_func();
1758 if (d)
1759 return d->revision;
1760 return 0;
1761}
1762
1763/*!
1764 Sets the \a revision of this method.
1765
1766 \sa revision()
1767*/
1768void QMetaMethodBuilder::setRevision(int revision)
1769{
1770 QMetaMethodBuilderPrivate *d = d_func();
1771 if (d) {
1772 d->revision = revision;
1773 if (revision)
1774 d->attributes |= MethodRevisioned;
1775 else
1776 d->attributes &= ~MethodRevisioned;
1777 }
1778}
1779
1780/*!
1781 \class QMetaPropertyBuilder
1782 \inmodule QtCore
1783 \internal
1784 \brief The QMetaPropertyBuilder class enables modifications to a property definition on a meta object builder.
1785*/
1786
1787QMetaPropertyBuilderPrivate *QMetaPropertyBuilder::d_func() const
1788{
1789 if (_mobj && _index >= 0 && _index < int(_mobj->d->properties.size()))
1790 return &(_mobj->d->properties[_index]);
1791 else
1792 return nullptr;
1793}
1794
1795/*!
1796 \fn QMetaPropertyBuilder::QMetaPropertyBuilder()
1797 \internal
1798*/
1799
1800/*!
1801 \fn int QMetaPropertyBuilder::index() const
1802
1803 Returns the index of this property within its QMetaObjectBuilder.
1804*/
1805
1806/*!
1807 Returns the name associated with this property.
1808
1809 \sa type()
1810*/
1811QByteArray QMetaPropertyBuilder::name() const
1812{
1813 QMetaPropertyBuilderPrivate *d = d_func();
1814 if (d)
1815 return d->name;
1816 else
1817 return QByteArray();
1818}
1819
1820/*!
1821 Returns the type associated with this property.
1822
1823 \sa name()
1824*/
1825QByteArray QMetaPropertyBuilder::type() const
1826{
1827 QMetaPropertyBuilderPrivate *d = d_func();
1828 if (d)
1829 return d->type;
1830 else
1831 return QByteArray();
1832}
1833
1834/*!
1835 Returns \c true if this property has a notify signal; false otherwise.
1836
1837 \sa notifySignal(), setNotifySignal(), removeNotifySignal()
1838*/
1839bool QMetaPropertyBuilder::hasNotifySignal() const
1840{
1841 QMetaPropertyBuilderPrivate *d = d_func();
1842 if (d)
1843 return d->notifySignal != -1;
1844 else
1845 return false;
1846}
1847
1848/*!
1849 Returns the notify signal associated with this property.
1850
1851 \sa hasNotifySignal(), setNotifySignal(), removeNotifySignal()
1852*/
1853QMetaMethodBuilder QMetaPropertyBuilder::notifySignal() const
1854{
1855 QMetaPropertyBuilderPrivate *d = d_func();
1856 if (d && d->notifySignal >= 0)
1857 return QMetaMethodBuilder(_mobj, d->notifySignal);
1858 else
1859 return QMetaMethodBuilder();
1860}
1861
1862/*!
1863 Sets the notify signal associated with this property to \a value.
1864
1865 \sa hasNotifySignal(), notifySignal(), removeNotifySignal()
1866*/
1867void QMetaPropertyBuilder::setNotifySignal(const QMetaMethodBuilder &value)
1868{
1869 QMetaPropertyBuilderPrivate *d = d_func();
1870 if (d) {
1871 if (value._mobj) {
1872 d->notifySignal = value._index;
1873 } else {
1874 d->notifySignal = -1;
1875 }
1876 }
1877}
1878
1879/*!
1880 Removes the notify signal from this property.
1881
1882 \sa hasNotifySignal(), notifySignal(), setNotifySignal()
1883*/
1884void QMetaPropertyBuilder::removeNotifySignal()
1885{
1886 QMetaPropertyBuilderPrivate *d = d_func();
1887 if (d)
1888 d->notifySignal = -1;
1889}
1890
1891/*!
1892 Returns \c true if this property is readable; otherwise returns \c false.
1893 The default value is true.
1894
1895 \sa setReadable(), isWritable()
1896*/
1897bool QMetaPropertyBuilder::isReadable() const
1898{
1899 QMetaPropertyBuilderPrivate *d = d_func();
1900 if (d)
1901 return d->flag(f: Readable);
1902 else
1903 return false;
1904}
1905
1906/*!
1907 Returns \c true if this property is writable; otherwise returns \c false.
1908 The default value is true.
1909
1910 \sa setWritable(), isReadable()
1911*/
1912bool QMetaPropertyBuilder::isWritable() const
1913{
1914 QMetaPropertyBuilderPrivate *d = d_func();
1915 if (d)
1916 return d->flag(f: Writable);
1917 else
1918 return false;
1919}
1920
1921/*!
1922 Returns \c true if this property can be reset to a default value; otherwise
1923 returns \c false. The default value is false.
1924
1925 \sa setResettable()
1926*/
1927bool QMetaPropertyBuilder::isResettable() const
1928{
1929 QMetaPropertyBuilderPrivate *d = d_func();
1930 if (d)
1931 return d->flag(f: Resettable);
1932 else
1933 return false;
1934}
1935
1936/*!
1937 Returns \c true if this property is designable; otherwise returns \c false.
1938 This default value is false.
1939
1940 \sa setDesignable(), isScriptable(), isStored()
1941*/
1942bool QMetaPropertyBuilder::isDesignable() const
1943{
1944 QMetaPropertyBuilderPrivate *d = d_func();
1945 if (d)
1946 return d->flag(f: Designable);
1947 else
1948 return false;
1949}
1950
1951/*!
1952 Returns \c true if the property is scriptable; otherwise returns \c false.
1953 This default value is true.
1954
1955 \sa setScriptable(), isDesignable(), isStored()
1956*/
1957bool QMetaPropertyBuilder::isScriptable() const
1958{
1959 QMetaPropertyBuilderPrivate *d = d_func();
1960 if (d)
1961 return d->flag(f: Scriptable);
1962 else
1963 return false;
1964}
1965
1966/*!
1967 Returns \c true if the property is stored; otherwise returns \c false.
1968 This default value is false.
1969
1970 \sa setStored(), isDesignable(), isScriptable()
1971*/
1972bool QMetaPropertyBuilder::isStored() const
1973{
1974 QMetaPropertyBuilderPrivate *d = d_func();
1975 if (d)
1976 return d->flag(f: Stored);
1977 else
1978 return false;
1979}
1980
1981/*!
1982 Returns \c true if this property is designated as the \c USER
1983 property, i.e., the one that the user can edit or that is
1984 significant in some other way. Otherwise it returns
1985 false. This default value is false.
1986
1987 \sa setUser(), isDesignable(), isScriptable()
1988*/
1989bool QMetaPropertyBuilder::isUser() const
1990{
1991 QMetaPropertyBuilderPrivate *d = d_func();
1992 if (d)
1993 return d->flag(f: User);
1994 else
1995 return false;
1996}
1997
1998/*!
1999 Returns \c true if the property has a C++ setter function that
2000 follows Qt's standard "name" / "setName" pattern. Designer and uic
2001 query hasStdCppSet() in order to avoid expensive
2002 QObject::setProperty() calls. All properties in Qt [should] follow
2003 this pattern. The default value is false.
2004
2005 \sa setStdCppSet()
2006*/
2007bool QMetaPropertyBuilder::hasStdCppSet() const
2008{
2009 QMetaPropertyBuilderPrivate *d = d_func();
2010 if (d)
2011 return d->flag(f: StdCppSet);
2012 else
2013 return false;
2014}
2015
2016/*!
2017 Returns \c true if the property is an enumerator or flag type;
2018 otherwise returns \c false. This default value is false.
2019
2020 \sa setEnumOrFlag()
2021*/
2022bool QMetaPropertyBuilder::isEnumOrFlag() const
2023{
2024 QMetaPropertyBuilderPrivate *d = d_func();
2025 if (d)
2026 return d->flag(f: EnumOrFlag);
2027 else
2028 return false;
2029}
2030
2031/*!
2032 Returns \c true if the property is constant; otherwise returns \c false.
2033 The default value is false.
2034*/
2035bool QMetaPropertyBuilder::isConstant() const
2036{
2037 QMetaPropertyBuilderPrivate *d = d_func();
2038 if (d)
2039 return d->flag(f: Constant);
2040 else
2041 return false;
2042}
2043
2044/*!
2045 Returns \c true if the property is final; otherwise returns \c false.
2046 The default value is false.
2047*/
2048bool QMetaPropertyBuilder::isFinal() const
2049{
2050 QMetaPropertyBuilderPrivate *d = d_func();
2051 if (d)
2052 return d->flag(f: Final);
2053 else
2054 return false;
2055}
2056
2057/*!
2058 * Returns \c true if the property is an alias.
2059 * The default value is false
2060 */
2061bool QMetaPropertyBuilder::isAlias() const
2062{
2063 QMetaPropertyBuilderPrivate *d = d_func();
2064 if (d)
2065 return d->flag(f: Alias);
2066 else
2067 return false;
2068}
2069
2070/*!
2071 Returns \c true if the property is bindable
2072 The default value is false
2073 */
2074bool QMetaPropertyBuilder::isBindable() const
2075{
2076 if (auto d = d_func())
2077 return d->flag(f: Bindable);
2078 else
2079 return false;
2080}
2081
2082/*!
2083 Sets this property to readable if \a value is true.
2084
2085 \sa isReadable(), setWritable()
2086*/
2087void QMetaPropertyBuilder::setReadable(bool value)
2088{
2089 QMetaPropertyBuilderPrivate *d = d_func();
2090 if (d)
2091 d->setFlag(f: Readable, value);
2092}
2093
2094/*!
2095 Sets this property to writable if \a value is true.
2096
2097 \sa isWritable(), setReadable()
2098*/
2099void QMetaPropertyBuilder::setWritable(bool value)
2100{
2101 QMetaPropertyBuilderPrivate *d = d_func();
2102 if (d)
2103 d->setFlag(f: Writable, value);
2104}
2105
2106/*!
2107 Sets this property to resettable if \a value is true.
2108
2109 \sa isResettable()
2110*/
2111void QMetaPropertyBuilder::setResettable(bool value)
2112{
2113 QMetaPropertyBuilderPrivate *d = d_func();
2114 if (d)
2115 d->setFlag(f: Resettable, value);
2116}
2117
2118/*!
2119 Sets this property to designable if \a value is true.
2120
2121 \sa isDesignable(), setScriptable(), setStored()
2122*/
2123void QMetaPropertyBuilder::setDesignable(bool value)
2124{
2125 QMetaPropertyBuilderPrivate *d = d_func();
2126 if (d)
2127 d->setFlag(f: Designable, value);
2128}
2129
2130/*!
2131 Sets this property to scriptable if \a value is true.
2132
2133 \sa isScriptable(), setDesignable(), setStored()
2134*/
2135void QMetaPropertyBuilder::setScriptable(bool value)
2136{
2137 QMetaPropertyBuilderPrivate *d = d_func();
2138 if (d)
2139 d->setFlag(f: Scriptable, value);
2140}
2141
2142/*!
2143 Sets this property to storable if \a value is true.
2144
2145 \sa isStored(), setDesignable(), setScriptable()
2146*/
2147void QMetaPropertyBuilder::setStored(bool value)
2148{
2149 QMetaPropertyBuilderPrivate *d = d_func();
2150 if (d)
2151 d->setFlag(f: Stored, value);
2152}
2153
2154/*!
2155 Sets the \c USER flag on this property to \a value.
2156
2157 \sa isUser(), setDesignable(), setScriptable()
2158*/
2159void QMetaPropertyBuilder::setUser(bool value)
2160{
2161 QMetaPropertyBuilderPrivate *d = d_func();
2162 if (d)
2163 d->setFlag(f: User, value);
2164}
2165
2166/*!
2167 Sets the C++ setter flag on this property to \a value, which is
2168 true if the property has a C++ setter function that follows Qt's
2169 standard "name" / "setName" pattern.
2170
2171 \sa hasStdCppSet()
2172*/
2173void QMetaPropertyBuilder::setStdCppSet(bool value)
2174{
2175 QMetaPropertyBuilderPrivate *d = d_func();
2176 if (d)
2177 d->setFlag(f: StdCppSet, value);
2178}
2179
2180/*!
2181 Sets this property to be of an enumerator or flag type if
2182 \a value is true.
2183
2184 \sa isEnumOrFlag()
2185*/
2186void QMetaPropertyBuilder::setEnumOrFlag(bool value)
2187{
2188 QMetaPropertyBuilderPrivate *d = d_func();
2189 if (d)
2190 d->setFlag(f: EnumOrFlag, value);
2191}
2192
2193/*!
2194 Sets the \c CONSTANT flag on this property to \a value.
2195
2196 \sa isConstant()
2197*/
2198void QMetaPropertyBuilder::setConstant(bool value)
2199{
2200 QMetaPropertyBuilderPrivate *d = d_func();
2201 if (d)
2202 d->setFlag(f: Constant, value);
2203}
2204
2205/*!
2206 Sets the \c FINAL flag on this property to \a value.
2207
2208 \sa isFinal()
2209*/
2210void QMetaPropertyBuilder::setFinal(bool value)
2211{
2212 QMetaPropertyBuilderPrivate *d = d_func();
2213 if (d)
2214 d->setFlag(f: Final, value);
2215}
2216
2217/*!
2218 Sets the \c ALIAS flag on this property to \a value
2219 */
2220void QMetaPropertyBuilder::setAlias(bool value)
2221{
2222 QMetaPropertyBuilderPrivate *d = d_func();
2223 if (d)
2224 d->setFlag(f: Alias, value);
2225}
2226
2227/*!
2228 Sets the\c BINDABLE flag on this property to \a value
2229 */
2230void QMetaPropertyBuilder::setBindable(bool value)
2231{
2232 if (auto d = d_func())
2233 d->setFlag(f: Bindable, value);
2234}
2235
2236/*!
2237 Returns the revision of this property.
2238
2239 \sa setRevision()
2240*/
2241int QMetaPropertyBuilder::revision() const
2242{
2243 QMetaPropertyBuilderPrivate *d = d_func();
2244 if (d)
2245 return d->revision;
2246 return 0;
2247}
2248
2249/*!
2250 Sets the \a revision of this property.
2251
2252 \sa revision()
2253*/
2254void QMetaPropertyBuilder::setRevision(int revision)
2255{
2256 QMetaPropertyBuilderPrivate *d = d_func();
2257 if (d)
2258 d->revision = revision;
2259}
2260
2261/*!
2262 \class QMetaEnumBuilder
2263 \inmodule QtCore
2264 \internal
2265 \brief The QMetaEnumBuilder class enables modifications to an enumerator definition on a meta object builder.
2266*/
2267
2268QMetaEnumBuilderPrivate *QMetaEnumBuilder::d_func() const
2269{
2270 if (_mobj && _index >= 0 && _index < int(_mobj->d->enumerators.size()))
2271 return &(_mobj->d->enumerators[_index]);
2272 else
2273 return nullptr;
2274}
2275
2276/*!
2277 \fn QMetaEnumBuilder::QMetaEnumBuilder()
2278 \internal
2279*/
2280
2281/*!
2282 \fn int QMetaEnumBuilder::index() const
2283
2284 Returns the index of this enumerator within its QMetaObjectBuilder.
2285*/
2286
2287/*!
2288 Returns the type name of the enumerator (without the scope).
2289*/
2290QByteArray QMetaEnumBuilder::name() const
2291{
2292 QMetaEnumBuilderPrivate *d = d_func();
2293 if (d)
2294 return d->name;
2295 else
2296 return QByteArray();
2297}
2298
2299/*!
2300 Returns the enum name of the enumerator (without the scope).
2301
2302 \since 5.12
2303*/
2304QByteArray QMetaEnumBuilder::enumName() const
2305{
2306 QMetaEnumBuilderPrivate *d = d_func();
2307 if (d)
2308 return d->enumName;
2309 else
2310 return QByteArray();
2311}
2312
2313/*!
2314 Sets this enumerator to have the enum name \c alias.
2315
2316 \since 5.12
2317 \sa isFlag(), enumName()
2318*/
2319void QMetaEnumBuilder::setEnumName(const QByteArray &alias)
2320{
2321 QMetaEnumBuilderPrivate *d = d_func();
2322 if (d)
2323 d->enumName = alias;
2324}
2325
2326/*!
2327 Returns the meta type of the enumerator.
2328
2329 \since 6.6
2330*/
2331QMetaType QMetaEnumBuilder::metaType() const
2332{
2333 if (QMetaEnumBuilderPrivate *d = d_func())
2334 return d->metaType;
2335 return QMetaType();
2336}
2337
2338/*!
2339 Sets this enumerator to have the given \c metaType. The is64Bit() flag will
2340 be set to match \a metaType's size.
2341
2342 \since 6.6
2343 \sa metaType()
2344*/
2345void QMetaEnumBuilder::setMetaType(QMetaType metaType)
2346{
2347 QMetaEnumBuilderPrivate *d = d_func();
2348 if (d) {
2349 d->metaType = metaType;
2350 setIs64Bit(metaType.sizeOf() > 4);
2351 }
2352}
2353
2354/*!
2355 Returns \c true if this enumerator is used as a flag; otherwise returns
2356 false.
2357
2358 \sa setIsFlag()
2359*/
2360bool QMetaEnumBuilder::isFlag() const
2361{
2362 QMetaEnumBuilderPrivate *d = d_func();
2363 if (d)
2364 return d->flags.toInt() & EnumIsFlag;
2365 else
2366 return false;
2367}
2368
2369/*!
2370 Sets this enumerator to be used as a flag if \a value is true.
2371
2372 \sa isFlag()
2373*/
2374void QMetaEnumBuilder::setIsFlag(bool value)
2375{
2376 QMetaEnumBuilderPrivate *d = d_func();
2377 if (d)
2378 d->flags.setFlag(flag: EnumIsFlag, on: value);
2379}
2380
2381/*!
2382 Return \c true if this enumerator should be considered scoped (C++11 enum class).
2383
2384 \sa setIsScoped()
2385*/
2386bool QMetaEnumBuilder::isScoped() const
2387{
2388 QMetaEnumBuilderPrivate *d = d_func();
2389 if (d)
2390 return d->flags.toInt() & EnumIsScoped;
2391 return false;
2392}
2393
2394/*!
2395 Sets this enumerator to be a scoped enum if \value is true
2396
2397 \sa isScoped()
2398*/
2399void QMetaEnumBuilder::setIsScoped(bool value)
2400{
2401 QMetaEnumBuilderPrivate *d = d_func();
2402 if (d)
2403 d->flags.setFlag(flag: EnumIsScoped, on: value);
2404}
2405
2406/*!
2407 Return \c true if this enumerations in this enumerator are 64-bit.
2408
2409 This flag is autoamtically enabled if a 64-bit value is added with addKey().
2410
2411 \sa setIs64Bit()
2412*/
2413bool QMetaEnumBuilder::is64Bit() const
2414{
2415 QMetaEnumBuilderPrivate *d = d_func();
2416 if (d)
2417 return d->flags.toInt() & EnumIs64Bit;
2418 return false;
2419}
2420
2421/*!
2422 Sets this enumerator to be 64-bit wide if \a value is true. If \a value is
2423 false, any stored 64-bit keys will be truncated to 32 bits.
2424
2425 This flag is autoamtically enabled if a 64-bit value is added with addKey().
2426
2427 \sa is64Bit()
2428*/
2429void QMetaEnumBuilder::setIs64Bit(bool value)
2430{
2431 QMetaEnumBuilderPrivate *d = d_func();
2432 if (d)
2433 d->flags.setFlag(flag: EnumIs64Bit, on: value);
2434}
2435
2436/*!
2437 Returns the number of keys.
2438
2439 \sa key(), addKey()
2440*/
2441int QMetaEnumBuilder::keyCount() const
2442{
2443 QMetaEnumBuilderPrivate *d = d_func();
2444 if (d)
2445 return d->keys.size();
2446 else
2447 return 0;
2448}
2449
2450/*!
2451 Returns the key with the given \a index, or an empty QByteArray
2452 if no such key exists.
2453
2454 \sa keyCount(), addKey(), value()
2455*/
2456QByteArray QMetaEnumBuilder::key(int index) const
2457{
2458 QMetaEnumBuilderPrivate *d = d_func();
2459 if (d && index >= 0 && index < d->keys.size())
2460 return d->keys[index];
2461 else
2462 return QByteArray();
2463}
2464
2465/*!
2466 Returns the value with the given \a index; or returns -1 if there
2467 is no such value.
2468
2469 If this is a 64-bit enumeration (see is64Bit()), this function returns the
2470 low 32-bit portion of the value. Use value64() to obtain the full value
2471 instead.
2472
2473 \sa value64(), keyCount(), addKey(), key(), is64Bit()
2474*/
2475int QMetaEnumBuilder::value(int index) const
2476{
2477 return value64(index).value_or(u: -1);
2478}
2479
2480/*!
2481 \since 6.9
2482
2483 Returns the value with the given \a index if it exists; or returns a
2484 disengaged \c{std::optional} if it doesn't.
2485
2486 \include qmetaobject.cpp qmetaenum-32bit-signextend-64bit
2487
2488 \sa keyCount(), key(), addKey()
2489*/
2490std::optional<quint64> QMetaEnumBuilder::value64(int index) const
2491{
2492 QMetaEnumBuilderPrivate *d = d_func();
2493 if (d && index >= 0 && index < d->keys.size()) {
2494 quint64 v = d->values[index];
2495 if (d->flags & EnumIs64Bit)
2496 return v;
2497 return uint(v); // return only the low 32 bits
2498 } else {
2499 return std::nullopt;
2500 }
2501}
2502
2503/*!
2504 Adds a new key called \a name to this enumerator, associated
2505 with \a value. Returns the index of the new key.
2506
2507 \sa keyCount(), key(), value(), removeKey()
2508*/
2509int QMetaEnumBuilder::addKey(const QByteArray &name, int value)
2510{
2511 QMetaEnumBuilderPrivate *d = d_func();
2512 if (d) {
2513 return d->addKey(name, value: uint(value));
2514 } else {
2515 return -1;
2516 }
2517}
2518
2519/*!
2520 \since 6.9
2521
2522 Adds a new key called \a name to this enumerator, associated
2523 with \a value. Returns the index of the new key.
2524
2525 Using the 64-bit version of this function automatically makes this
2526 enumeration be stored as 64-bit.
2527
2528 \sa keyCount(), key(), value(), removeKey(), is64Bit()
2529*/
2530int QMetaEnumBuilder::addKey(const QByteArray &name, quint64 value)
2531{
2532 QMetaEnumBuilderPrivate *d = d_func();
2533 if (d) {
2534 setIs64Bit(true);
2535 return d->addKey(name, value);
2536 }
2537 return -1;
2538}
2539
2540/*!
2541 Removes the key at \a index from this enumerator.
2542
2543 \sa addKey()
2544*/
2545void QMetaEnumBuilder::removeKey(int index)
2546{
2547 QMetaEnumBuilderPrivate *d = d_func();
2548 if (d && index >= 0 && index < d->keys.size()) {
2549 d->keys.removeAt(i: index);
2550 d->values.removeAt(i: index);
2551 }
2552}
2553
2554QT_END_NAMESPACE
2555

source code of qtbase/src/corelib/kernel/qmetaobjectbuilder.cpp