1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the examples of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:BSD$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** BSD License Usage
18** Alternatively, you may use this file under the terms of the BSD license
19** as follows:
20**
21** "Redistribution and use in source and binary forms, with or without
22** modification, are permitted provided that the following conditions are
23** met:
24** * Redistributions of source code must retain the above copyright
25** notice, this list of conditions and the following disclaimer.
26** * Redistributions in binary form must reproduce the above copyright
27** notice, this list of conditions and the following disclaimer in
28** the documentation and/or other materials provided with the
29** distribution.
30** * Neither the name of The Qt Company Ltd nor the names of its
31** contributors may be used to endorse or promote products derived
32** from this software without specific prior written permission.
33**
34**
35** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46**
47** $QT_END_LICENSE$
48**
49****************************************************************************/
50
51#include <QtScript/QScriptClassPropertyIterator>
52#include <QtScript/QScriptContext>
53#include <QtScript/QScriptEngine>
54#include "bytearrayclass.h"
55#include "bytearrayprototype.h"
56
57#include <stdlib.h>
58
59Q_DECLARE_METATYPE(QByteArray*)
60Q_DECLARE_METATYPE(ByteArrayClass*)
61
62class ByteArrayClassPropertyIterator : public QScriptClassPropertyIterator
63{
64public:
65 ByteArrayClassPropertyIterator(const QScriptValue &object);
66 ~ByteArrayClassPropertyIterator();
67
68 bool hasNext() const;
69 void next();
70
71 bool hasPrevious() const;
72 void previous();
73
74 void toFront();
75 void toBack();
76
77 QScriptString name() const;
78 uint id() const;
79
80private:
81 int m_index;
82 int m_last;
83};
84
85//! [0]
86ByteArrayClass::ByteArrayClass(QScriptEngine *engine)
87 : QObject(engine), QScriptClass(engine)
88{
89 qScriptRegisterMetaType<QByteArray>(eng: engine, toScriptValue, fromScriptValue);
90
91 length = engine->toStringHandle(str: QLatin1String("length"));
92
93 proto = engine->newQObject(object: new ByteArrayPrototype(this),
94 ownership: QScriptEngine::QtOwnership,
95 options: QScriptEngine::SkipMethodsInEnumeration
96 | QScriptEngine::ExcludeSuperClassMethods
97 | QScriptEngine::ExcludeSuperClassProperties);
98 QScriptValue global = engine->globalObject();
99 proto.setPrototype(global.property(name: "Object").property(name: "prototype"));
100
101 ctor = engine->newFunction(signature: construct, prototype: proto);
102 ctor.setData(engine->toScriptValue(value: this));
103}
104//! [0]
105
106ByteArrayClass::~ByteArrayClass()
107{
108}
109
110//! [3]
111QScriptClass::QueryFlags ByteArrayClass::queryProperty(const QScriptValue &object,
112 const QScriptString &name,
113 QueryFlags flags, uint *id)
114{
115 QByteArray *ba = qscriptvalue_cast<QByteArray*>(value: object.data());
116 if (!ba)
117 return {};
118 if (name == length) {
119 return flags;
120 } else {
121 bool isArrayIndex;
122 qint32 pos = name.toArrayIndex(ok: &isArrayIndex);
123 if (!isArrayIndex)
124 return {};
125 *id = pos;
126 if ((flags & HandlesReadAccess) && (pos >= ba->size()))
127 flags &= ~HandlesReadAccess;
128 return flags;
129 }
130}
131//! [3]
132
133//! [4]
134QScriptValue ByteArrayClass::property(const QScriptValue &object,
135 const QScriptString &name, uint id)
136{
137 QByteArray *ba = qscriptvalue_cast<QByteArray*>(value: object.data());
138 if (!ba)
139 return QScriptValue();
140 if (name == length) {
141 return ba->length();
142 } else {
143 qint32 pos = id;
144 if ((pos < 0) || (pos >= ba->size()))
145 return QScriptValue();
146 return uint(ba->at(i: pos)) & 255;
147 }
148 return QScriptValue();
149}
150//! [4]
151
152//! [5]
153void ByteArrayClass::setProperty(QScriptValue &object,
154 const QScriptString &name,
155 uint id, const QScriptValue &value)
156{
157 QByteArray *ba = qscriptvalue_cast<QByteArray*>(value: object.data());
158 if (!ba)
159 return;
160 if (name == length) {
161 resize(ba&: *ba, newSize: value.toInt32());
162 } else {
163 qint32 pos = id;
164 if (pos < 0)
165 return;
166 if (ba->size() <= pos)
167 resize(ba&: *ba, newSize: pos + 1);
168 (*ba)[pos] = char(value.toInt32());
169 }
170}
171//! [5]
172
173//! [6]
174QScriptValue::PropertyFlags ByteArrayClass::propertyFlags(
175 const QScriptValue &/*object*/, const QScriptString &name, uint /*id*/)
176{
177 if (name == length) {
178 return QScriptValue::Undeletable
179 | QScriptValue::SkipInEnumeration;
180 }
181 return QScriptValue::Undeletable;
182}
183//! [6]
184
185//! [7]
186QScriptClassPropertyIterator *ByteArrayClass::newIterator(const QScriptValue &object)
187{
188 return new ByteArrayClassPropertyIterator(object);
189}
190//! [7]
191
192QString ByteArrayClass::name() const
193{
194 return QLatin1String("ByteArray");
195}
196
197QScriptValue ByteArrayClass::prototype() const
198{
199 return proto;
200}
201
202QScriptValue ByteArrayClass::constructor()
203{
204 return ctor;
205}
206
207//! [10]
208QScriptValue ByteArrayClass::newInstance(int size)
209{
210 engine()->reportAdditionalMemoryCost(size);
211 return newInstance(ba: QByteArray(size, /*ch=*/0));
212}
213//! [10]
214
215//! [1]
216QScriptValue ByteArrayClass::newInstance(const QByteArray &ba)
217{
218 QScriptValue data = engine()->newVariant(value: QVariant::fromValue(value: ba));
219 return engine()->newObject(scriptClass: this, data);
220}
221//! [1]
222
223//! [2]
224QScriptValue ByteArrayClass::construct(QScriptContext *ctx, QScriptEngine *)
225{
226 ByteArrayClass *cls = qscriptvalue_cast<ByteArrayClass*>(value: ctx->callee().data());
227 if (!cls)
228 return QScriptValue();
229 QScriptValue arg = ctx->argument(index: 0);
230 if (arg.instanceOf(other: ctx->callee()))
231 return cls->newInstance(ba: qscriptvalue_cast<QByteArray>(value: arg));
232 int size = arg.toInt32();
233 return cls->newInstance(size);
234}
235//! [2]
236
237QScriptValue ByteArrayClass::toScriptValue(QScriptEngine *eng, const QByteArray &ba)
238{
239 QScriptValue ctor = eng->globalObject().property(name: "ByteArray");
240 ByteArrayClass *cls = qscriptvalue_cast<ByteArrayClass*>(value: ctor.data());
241 if (!cls)
242 return eng->newVariant(value: QVariant::fromValue(value: ba));
243 return cls->newInstance(ba);
244}
245
246void ByteArrayClass::fromScriptValue(const QScriptValue &obj, QByteArray &ba)
247{
248 ba = qvariant_cast<QByteArray>(v: obj.data().toVariant());
249}
250
251//! [9]
252void ByteArrayClass::resize(QByteArray &ba, int newSize)
253{
254 int oldSize = ba.size();
255 ba.resize(size: newSize);
256 if (newSize > oldSize)
257 engine()->reportAdditionalMemoryCost(size: newSize - oldSize);
258}
259//! [9]
260
261
262
263ByteArrayClassPropertyIterator::ByteArrayClassPropertyIterator(const QScriptValue &object)
264 : QScriptClassPropertyIterator(object)
265{
266 toFront();
267}
268
269ByteArrayClassPropertyIterator::~ByteArrayClassPropertyIterator()
270{
271}
272
273//! [8]
274bool ByteArrayClassPropertyIterator::hasNext() const
275{
276 QByteArray *ba = qscriptvalue_cast<QByteArray*>(value: object().data());
277 return m_index < ba->size();
278}
279
280void ByteArrayClassPropertyIterator::next()
281{
282 m_last = m_index;
283 ++m_index;
284}
285
286bool ByteArrayClassPropertyIterator::hasPrevious() const
287{
288 return (m_index > 0);
289}
290
291void ByteArrayClassPropertyIterator::previous()
292{
293 --m_index;
294 m_last = m_index;
295}
296
297void ByteArrayClassPropertyIterator::toFront()
298{
299 m_index = 0;
300 m_last = -1;
301}
302
303void ByteArrayClassPropertyIterator::toBack()
304{
305 QByteArray *ba = qscriptvalue_cast<QByteArray*>(value: object().data());
306 m_index = ba->size();
307 m_last = -1;
308}
309
310QScriptString ByteArrayClassPropertyIterator::name() const
311{
312 return object().engine()->toStringHandle(str: QString::number(m_last));
313}
314
315uint ByteArrayClassPropertyIterator::id() const
316{
317 return m_last;
318}
319//! [8]
320

source code of qtscript/examples/script/customclass/bytearrayclass.cpp