void ReflectiveScriptClass::setProperty( QScriptValue& object, const QScriptString & name, uint id, const QScriptValue& value) { // std::cout << __FUNCTION__ << " " << // name.toString().toStdString() << std::endl; Node_ptr node = qscriptvalue_cast< Node_ptr >(object.data()); if (node) { // Ensure it is initialized node->check_for_initialized(); ::gsim::core::descriptor_type type = node->descriptor->get_type(); if (type == ::gsim::core::TYPE_STRUCT) { // because I am sure it is initialized if (id < node->children.size()) { fromScriptValue(value, node->children[id]); } } else if (node->descriptor->is_repeated()) { if (id < node->children.size()) { fromScriptValue(value, node->children[id]); } else if (node->descriptor->is_variable_length() && QString(name) == "length") { // length property unsigned int length = value.toUInt32(); node->descriptor->set_length(node->holder, length); // re-initialized in next access node->reset(); } } } }
QScriptValue ReflectiveScriptClass::property( const QScriptValue& object, const QScriptString& name, uint id) { // std::cout << __FUNCTION__ << std::endl; Node_ptr node = qscriptvalue_cast< Node_ptr >(object.data()); if (node) { node->check_for_initialized(); ::gsim::core::descriptor_type type = node->descriptor->get_type(); if (type == ::gsim::core::TYPE_STRUCT) { if (id < node->children.size()) { return toScriptValue(node->children[id]); } } else if (node->descriptor->is_repeated()) { if (id < node->children.size()) { return toScriptValue(node->children[id]); } else if (QString(name) == "length") { // length property return QScriptValue((uint) node->children.size()); } } } // Invalid value return QScriptValue(); }
QScriptClass::QueryFlags ReflectiveScriptClass::queryProperty( const QScriptValue& object, const QScriptString& name, QScriptClass::QueryFlags flags, uint * id) { // std::cout << __FUNCTION__ << " " << // name.toString().toStdString() << std::endl; // Invalid property identifier *id = std::numeric_limits< uint >::max(); // Seen in Qt examples Node_ptr node = qscriptvalue_cast< Node_ptr >(object.data()); if (node) { // Conversion from interned to normal string // for comparision const QString sName = name; node->check_for_initialized(); ::gsim::core::descriptor_type type = node->descriptor->get_type(); if (type == ::gsim::core::TYPE_STRUCT) { unsigned int count = node->descriptor->get_children_count(); // Search by name for (unsigned int i = 0; i < count; i++) { // Maybe better with interned strings if (sName == node->descriptor->get_child_name(i)) { // Its identifier is its position *id = i; return QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess; } } } else if (node->descriptor->is_repeated()) { unsigned int count = node->descriptor->get_length(node->holder); bool ok = false; *id = sName.toUInt(&ok); if (ok && *id < count) { return QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess; } else if (!ok && sName == "length") { *id = std::numeric_limits< uint >::max(); if (node->descriptor->is_variable_length()) return QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess; return QScriptClass::HandlesReadAccess; } } } else { std::cerr << "Invalid node!" << std::endl; } return 0; }
void ReflectiveScriptClass::fromScriptValue( const QScriptValue& value, Node_ptr node) { // std::cout << __FUNCTION__ << std::endl; using namespace gsim::core; const descriptor_type type = node->descriptor->get_type(); node->check_for_initialized(); holder& hold = node->holder; descriptor_base const * descriptor = node->descriptor; switch(type) { case TYPE_STRUCT: { if (value.isObject()) { unsigned int count = node->descriptor->get_children_count(); // Search by name for (unsigned int i = 0; i < count; i++) { const char *childName = descriptor->get_child_name(i); QScriptValue childValue = value.property(childName); if (childValue.isValid()) fromScriptValue(childValue, node->children[i]); } } else { std::cerr << "Must be an object!" << std::endl; } } break; case TYPE_ARRAY: if (descriptor->get_slice()->get_type() == TYPE_CHAR) { const std::string str(value.toString().toStdString()); descriptor->from_string(hold, str); break; } case TYPE_SEQUENCE: { unsigned int length = descriptor->get_length(hold); unsigned int newLength = value.property("length").toUInt32(); if (descriptor->is_variable_length() && length != newLength) { descriptor->set_length(hold, newLength); node->reset(); node->check_for_initialized(); } for (unsigned int i = 0; i < newLength && i < length; i++) { fromScriptValue(value.property(i), node->children[i]); } } break; case TYPE_BOOL: hold.to_value< bool >() = value.toBool(); break; case TYPE_OCTET: hold.to_value< unsigned char >() = value.toInteger(); break; case TYPE_CHAR: hold.to_value< char >() = value.toInteger(); break; case TYPE_SHORT: hold.to_value< short >() = value.toInteger(); break; case TYPE_USHORT: hold.to_value< unsigned short >() = value.toUInt16(); break; case TYPE_LONG: hold.to_value< int32_t >() = value.toInteger(); break; case TYPE_ULONG: hold.to_value< uint32_t >() = value.toUInt32(); break; case TYPE_LONGLONG: hold.to_value< int64_t >() = value.toInteger(); break; case TYPE_ULONGLONG: hold.to_value< uint64_t >() = value.toInteger(); break; case TYPE_STRING: case TYPE_WSTRING: { const std::string str(value.toString().toStdString()); descriptor->from_string(hold, str); } break; case TYPE_ENUM: { const unsigned int count = descriptor->get_children_count(); const QString str (value.toString()); unsigned int idx = descriptor->get_child_index( str.toStdString().c_str()); if (idx < count) { core::holder tmp( descriptor->get_child_value(hold, idx)); descriptor->copy(tmp, hold); } // TODO debería devolverse excepción si se introdujo // un literal no válido. } break; case TYPE_DOUBLE: hold.to_value< double >() = value.toNumber(); break; case TYPE_FLOAT: hold.to_value< float >() = value.toNumber(); default: break; } }