BaseGDL* _GDL_OBJECT_OverloadBracketsRightSide( EnvUDT* e) { // // debug/check // std::cout << "_GDL_OBJECT_OverloadBracketsRightSide called" << std::endl; SizeT nParam = e->NParam(); // number of parameters actually given // int envSize = e->EnvSize(); // number of parameters + keywords 'e' (pro) has defined if( nParam < 3) // consider implicit SELF ThrowFromInternalUDSub( e, "At least 2 parameters are needed: ISRANGE, SUB1 [, ...]."); // default behavior: Exact like scalar indexing BaseGDL* isRange = e->GetKW(1); if( isRange == NULL) ThrowFromInternalUDSub( e, "Parameter 1 (ISRANGE) is undefined."); if( isRange->Rank() == 0) ThrowFromInternalUDSub( e, "Parameter 1 (ISRANGE) must be an array in this context: " + e->Caller()->GetString(e->GetKW(1))); SizeT nIsRange = isRange->N_Elements(); if( nIsRange > (nParam - 2)) //- SELF and ISRANGE ThrowFromInternalUDSub( e, "Parameter 1 (ISRANGE) must have "+i2s(nParam-2)+" elements."); Guard<DLongGDL> isRangeLongGuard; DLongGDL* isRangeLong; if( isRange->Type() == GDL_LONG) isRangeLong = static_cast<DLongGDL*>( isRange); else { try{ isRangeLong = static_cast<DLongGDL*>( isRange->Convert2( GDL_LONG, BaseGDL::COPY)); } catch( GDLException& ex) { ThrowFromInternalUDSub( e, ex.ANTLRException::getMessage()); } isRangeLongGuard.Reset( isRangeLong); } ArrayIndexVectorT ixList; // IxExprListT exprList; try { for( int p=0; p<nIsRange; ++p) { BaseGDL* parX = e->GetKW( p + 2); // implicit SELF, ISRANGE, par1..par8 if( parX == NULL) ThrowFromInternalUDSub( e, "Parameter is undefined: " + e->Caller()->GetString(e->GetKW( p + 2))); DLong isRangeX = (*isRangeLong)[p]; if( isRangeX != 0 && isRangeX != 1) { ThrowFromInternalUDSub( e, "Value of parameter 1 (ISRANGE["+i2s(p)+"]) is out of allowed range."); } if( isRangeX == 1) { if( parX->N_Elements() != 3) { ThrowFromInternalUDSub( e, "Range vector must have 3 elements: " + e->Caller()->GetString(e->GetKW( p + 2))); } DLongGDL* parXLong; Guard<DLongGDL> parXLongGuard; if( parX->Type() != GDL_LONG) { try{ parXLong = static_cast<DLongGDL*>( parX->Convert2( GDL_LONG, BaseGDL::COPY)); parXLongGuard.Reset( parXLong); } catch( GDLException& ex) { ThrowFromInternalUDSub( e, ex.ANTLRException::getMessage()); } } else { parXLong = static_cast<DLongGDL*>( parX); } // negative end ix is fine -> CArrayIndexRangeS can handle [b:*:s] ([b,-1,s]) ixList.push_back(new CArrayIndexRangeS( (*parXLong)[0], (*parXLong)[1], (*parXLong)[2])); } else // non-range { // ATTENTION: These two grab c1 (all others don't) // a bit unclean, but for maximum efficiency if( parX->Rank() == 0) ixList.push_back( new CArrayIndexScalar( parX->Dup())); else ixList.push_back( new CArrayIndexIndexed( parX->Dup())); } } // for } catch( GDLException& ex) { ixList.Destruct(); // ixList is not valid afterwards, but as we throw this is ok throw ex; } ArrayIndexListT* aL; MakeArrayIndex( &ixList, &aL, NULL); // important to get the non-NoAssoc ArrayIndexListT // because only they clean up ixList on destruction Guard< ArrayIndexListT> aLGuard( aL); IxExprListT ixL; return aL->Index( e->GetKW( 0), ixL); // index SELF }