XS_this and the argument stack.
Matt Newell <[email protected]> Mon, 10 Jan 2005 13:42:37 -0800
| Newsgroups | gmane.comp.kde.devel.perl |
|---|---|
| Message-ID | <[email protected]> |
Hello I've recently been integrating my homegrown database class library(built on top of QSqlDatabase etc.) into a hacked up version of perlqt 3.008. I've already gotten it working well, but now I'm in the process of converting a lot of existing perl code to use it, and I'm really finding that I don't like the fact that the this object is taken off of the arguement stack. I was just wondering if there is a reason why this is required, or if it was simply done as convenience. I'm pretty sure that I can remove it, but I just wanted to check and make sure that it wasn't going to bite me in the ass. BTW, I've modified my version with full marshalling support for QVariant, and QValueList<QVariant>. So far the marshaller supports Int, UInt, LongLong->Int, ULongLong->UInt, Date -> Qt::Date, DateTime ->Qt::DateTime, Time -> Qt::Time, and String. I think that this would be a valueable contribution to perlqt, so I've attached the code. Matt _______________________________________________ Kde-perl mailing list [email protected] https://mail.kde.org/mailman/listinfo/kde-perl
temp.cpp
(text/x-c++src, 8.1 KB)
void marshall_QValueListQVariant( Marshall * m )
{
Smoke * smoke = m->smoke();
int dateId = smoke->idClass( "QDate" );
int dateTimeId = smoke->idClass( "QDateTime" );
int timeId = smoke->idClass( "QTime" );
switch( m->action() ) {
case Marshall::FromSV:
{
SV *sv = m->var();
if(!SvROK(sv) || SvTYPE(SvRV(sv)) != SVt_PVAV || av_len((AV*)SvRV(sv)) < 0) {
m->item().s_voidp = 0;
break;
}
QValueList<QVariant> *varlist = new QValueList<QVariant>;
m->item().s_voidp = (void*)varlist;
AV *list = (AV*)SvRV(sv);
int count = av_len(list);
int i;
for(i = 0; i <= count; i++) {
SV **item = av_fetch(list, i, 0);
if(!item || !SvOK(*item)) {
varlist->append( QVariant( QString::null ) );
continue;
}
SV * svitem = *item;
smokeperl_object * o = 0;
if( SvIOK(svitem) ) {
if( SvUOK(svitem) )
varlist->append( QVariant( (uint)SvUV(svitem) ) );
else
varlist->append( QVariant( (int)SvIV(svitem) ) );
} else if( SvPOK(svitem) ) {
COP *cop = cxstack[cxstack_ix].blk_oldcop;
bool lc = cop->op_private & HINT_LOCALE;
if(SvUTF8(svitem))
varlist->append( QVariant( QString::fromUtf8(SvPV_nolen(svitem)) ) );
else if(lc)
varlist->append(QVariant(QString::fromLocal8Bit(SvPV_nolen(svitem))) );
else
varlist->append(QVariant(QString::fromLatin1(SvPV_nolen(svitem))));
} else if( o=sv_obj_info(svitem) ) {
if(!o->ptr) {
varlist->append( QVariant( QString::null ) );
} else {
void *ptr = o->ptr;
if( o->classId == timeId )
varlist->append( QVariant( *((QTime*)ptr) ) );
else if( o->classId == dateTimeId )
varlist->append( QVariant( *((QDateTime*)ptr) ) );
else if( o->classId = dateId )
varlist->append( QVariant( *((QDate*)ptr) ) );
else
varlist->append( QVariant( QString::null ) );
}
}
}
m->next();
if( m->cleanup() ) {
delete varlist;
}
break;
}
case Marshall::ToSV:
{
QValueList<QVariant> *vvlist = (QValueList<QVariant>*)m->item().s_voidp;
if(!vvlist) {
sv_setsv_mg(m->var(), &PL_sv_undef);
break;
}
AV * av = newAV();
{
SV * rv = newRV_noinc((SV*)av);
sv_setsv_mg(m->var(), rv);
SvREFCNT_dec(rv);
}
for( QValueListIterator<QVariant> it = vvlist->begin(); it != vvlist->end(); ++it )
{
// No need for getPointerObject, because we just created this pointer
QVariant & v = *it;
int id = 0;
void * voidp=0;
char * cn=0;
switch( v.type() ) {
case QVariant::LongLong:
case QVariant::Int:
{
SV * sv = newSViv( v.toInt() );
av_push( av, sv );
}
break;
case QVariant::ULongLong:
case QVariant::UInt:
{
SV * sv = newSVuv( v.toUInt() );
av_push( av, sv );
}
break;
case QVariant::Double:
{
SV * sv = newSVnv( v.toDouble() );
av_push( av, sv );
}
break;
case QVariant::String:
{
COP *cop = cxstack[cxstack_ix].blk_oldcop;
if(!(cop->op_private & HINT_BYTES)) {
SV *sv = newSVpv((const char *)v.toString().utf8(), 0);
SvUTF8_on(sv);
av_push(av, sv);
}
else if(cop->op_private & HINT_LOCALE) {
SV *sv = newSVpv((const char *)v.toString().local8Bit(), 0);
av_push(av, sv);
}
else {
SV *sv = newSVpv((const char *)v.toString().latin1(), 0);
av_push(av, sv);
}
}
break;
case QVariant::Date:
voidp = (void*)(new QDate( v.toDate() ));
id = dateId;
cn = "Qt::Date";
break;
case QVariant::DateTime:
voidp = (void*)(new QDateTime( v.toDateTime() ));
id = dateTimeId;
cn = "Qt::DateTime";
break;
case QVariant::Time:
voidp = (void*)(new QTime( v.toTime() ));
id = timeId;
cn = "Qt::Time";
break;
default:
warn( "Couldn't marshall QVariant type %s", v.typeName() );
break;
}
if( voidp ) {
SV *ret= newSV(0);
HV *hv = newHV();
SV *obj = newRV_noinc((SV*)hv);
smokeperl_object o;
o.smoke = smoke;
o.classId = id;
o.ptr = voidp;
o.allocated = true;
sv_bless(obj, gv_stashpv( cn, TRUE) );
sv_magic((SV*)hv, sv_qapp, '~', (char*)&o, sizeof(o));
MAGIC *mg = mg_find((SV*)hv, '~');
mg->mg_virtual = &vtbl_smoke;
sv_setsv_mg(ret, obj);
av_push(av,ret);
SvREFCNT_dec(obj);
}
}
if( m->cleanup() )
delete vvlist;
break;
}
default:
break;
}
}
void marshall_QVariant(Marshall * m)
{
Smoke * smoke = m->smoke();
int dateId = smoke->idClass( "QDate" );
int dateTimeId = smoke->idClass( "QDateTime" );
int timeId = smoke->idClass( "QTime" );
switch( m->action() ) {
case Marshall::FromSV:
{
SV *sv = m->var();
if( !SvOK(sv) ) {
m->item().s_voidp = 0;
break;
}
smokeperl_object * o = 0;
if( SvIOK(sv) ) {
if( SvUOK(sv) )
m->item().s_voidp = new QVariant( (uint)SvUV(sv) );
else
m->item().s_voidp = new QVariant( (int)SvIV(sv) );
} else if( SvNOK(sv) ) {
m->item().s_voidp = new QVariant( (double)SvNV(sv) );
} else if( SvPOK(sv) ) {
COP *cop = cxstack[cxstack_ix].blk_oldcop;
bool lc = cop->op_private & HINT_LOCALE;
if(SvUTF8(sv))
m->item().s_voidp = new QVariant( QString::fromUtf8(SvPV_nolen(sv)) );
else if(lc)
m->item().s_voidp = new QVariant( QString::fromLocal8Bit(SvPV_nolen(sv)) );
else
m->item().s_voidp = new QVariant( QString::fromLatin1(SvPV_nolen(sv)) );
} else if( o = sv_obj_info(sv) ) {
if(!o->ptr) {
m->item().s_voidp = 0;
} else {
void *ptr = o->ptr;
if( o->classId == timeId )
m->item().s_voidp = new QVariant( *((QTime*)ptr) );
else if( o->classId == dateTimeId )
m->item().s_voidp = new QVariant( *((QDateTime*)ptr) );
else if( o->classId = dateId )
m->item().s_voidp = new QVariant( *((QDate*)ptr) );
else
m->item().s_voidp = 0;
}
}
m->next();
if( m->cleanup() && m->item().s_voidp ) {
delete (QVariant*)m->item().s_voidp;
}
break;
}
case Marshall::ToSV:
{
QVariant *var = (QVariant*)m->item().s_voidp;
if(!var) {
warn( "QVariant Pointer is null" );
sv_setsv_mg(m->var(), &PL_sv_undef);
break;
}
int id = 0;
void * voidp=0;
char * cn=0;
//warn( var->typeName() );
switch( var->type() ) {
case QVariant::Int:
case QVariant::LongLong:
sv_setiv_mg(m->var(), (IV)var->toInt() );
break;
case QVariant::UInt:
case QVariant::ULongLong:
sv_setuv_mg(m->var(), (UV)var->toUInt() );
break;
case QVariant::Double:
sv_setnv_mg(m->var(), (NV)var->toDouble() );
break;
case QVariant::String:
{
COP *cop = cxstack[cxstack_ix].blk_oldcop;
if(!(cop->op_private & HINT_BYTES)) {
sv_setpv_mg(m->var(), (const char *)var->toString().utf8());
SvUTF8_on(m->var());
}
else if(cop->op_private & HINT_LOCALE) {
sv_setpv_mg(m->var(), (const char *)var->toString().local8Bit());
}
else {
sv_setpv_mg(m->var(), (const char *)var->toString().latin1());
}
}
break;
case QVariant::Date:
voidp = (void*)(new QDate( var->toDate() ));
id = dateId;
cn = " Qt::Date";
break;
case QVariant::DateTime:
voidp = (void*)(new QDateTime( var->toDateTime() ));
id = dateTimeId;
cn = " Qt::DateTime";
break;
case QVariant::Time:
voidp = (void*)(new QTime( var->toTime() ));
id = timeId;
cn = " Qt::Time";
break;
default:
warn( "Couldn't marshall QVariant type %s", var->typeName() );
break;
}
if( voidp ) {
HV *hv = newHV();
SV *obj = newRV_noinc((SV*)hv);
smokeperl_object o;
o.smoke = smoke;
o.classId = id;
o.ptr = voidp;
o.allocated = true;
sv_bless(obj, gv_stashpv( cn, TRUE) );
sv_magic((SV*)hv, sv_qapp, '~', (char*)&o, sizeof(o));
MAGIC *mg = mg_find((SV*)hv, '~');
mg->mg_virtual = &vtbl_smoke;
sv_setsv_mg(m->var(), obj);
SvREFCNT_dec(obj);
}
if( m->cleanup() )
delete var;
break;
}
default:
break;
}
}