Esempio n. 1
0
    /*
    ** This function is similar to sqlite3ExprDup(), except that if pzBuffer
    ** is not NULL then *pzBuffer is assumed to point to a buffer large enough
    ** to store the copy of expression p, the copies of p->u.zToken
    ** (if applicable), and the copies of the p->pLeft and p->pRight expressions,
    ** if any. Before returning, *pzBuffer is set to the first byte passed the
    ** portion of the buffer copied into by this function.
    */
    static Expr exprDup( sqlite3 db, Expr p, int flags, ref Expr pzBuffer )
    {
      Expr pNew = null;                      /* Value to return */
      if ( p != null )
      {
        bool isReduced = ( flags & EXPRDUP_REDUCE ) != 0;
        Expr zAlloc = new Expr();
        u32 staticFlag = 0;

        Debug.Assert( pzBuffer == null || isReduced );

        /* Figure out where to write the new Expr structure. */
        //if ( pzBuffer !=null)
        //{
        //  zAlloc = pzBuffer;
        //  staticFlag = EP_Static;
        //}
        //else
        //{
        //  zAlloc = new Expr();//sqlite3DbMallocRaw( db, dupedExprSize( p, flags ) );
        //}
        pNew = p.Copy_Minimal();// (Expr*)zAlloc;

        if ( pNew != null )
        {
          /* Set nNewSize to the size allocated for the structure pointed to
          ** by pNew. This is either EXPR_FULLSIZE, EXPR_REDUCEDSIZE or
          ** EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed
          ** by the copy of the p->u.zToken string (if any).
          */
          int nStructSize = dupedExprStructSize( p, flags );
          int nNewSize = nStructSize & 0xfff;
          int nToken;
          if ( !ExprHasProperty( p, EP_IntValue ) && !String.IsNullOrEmpty( p.u.zToken ) )
          {
            nToken = sqlite3Strlen30( p.u.zToken );
          }
          else
          {
            nToken = 0;
          }
          if ( isReduced )
          {
            Debug.Assert( !ExprHasProperty( p, EP_Reduced ) );
            //memcpy( zAlloc, p, nNewSize );
          }
          else
          {
            int nSize = exprStructSize( p );
            //memcpy( zAlloc, p, nSize );
            //memset( &zAlloc[nSize], 0, EXPR_FULLSIZE - nSize );
          }

          /* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */
          unchecked { pNew.flags &= (ushort)( ~( EP_Reduced | EP_TokenOnly | EP_Static ) ); }
          pNew.flags |= (ushort)( nStructSize & ( EP_Reduced | EP_TokenOnly ) );
          pNew.flags |= (ushort)staticFlag;

          /* Copy the p->u.zToken string, if any. */
          if ( nToken != 0 )
          {
            string zToken;// = pNew.u.zToken = (char*)&zAlloc[nNewSize];
            zToken = p.u.zToken.Substring( 0, nToken );// memcpy( zToken, p.u.zToken, nToken );
          }

          if ( 0 == ( ( p.flags | pNew.flags ) & EP_TokenOnly ) )
          {
            /* Fill in the pNew.x.pSelect or pNew.x.pList member. */
            if ( ExprHasProperty( p, EP_xIsSelect ) )
            {
              pNew.x.pSelect = sqlite3SelectDup( db, p.x.pSelect, isReduced ? 1 : 0 );
            }
            else
            {
              pNew.x.pList = sqlite3ExprListDup( db, p.x.pList, isReduced ? 1 : 0 );
            }
          }

          /* Fill in pNew.pLeft and pNew.pRight. */
          if ( ExprHasAnyProperty( pNew, EP_Reduced | EP_TokenOnly ) )
          {
            //zAlloc += dupedExprNodeSize( p, flags );
            if ( ExprHasProperty( pNew, EP_Reduced ) )
            {
              pNew.pLeft = exprDup( db, p.pLeft, EXPRDUP_REDUCE, ref zAlloc );
              pNew.pRight = exprDup( db, p.pRight, EXPRDUP_REDUCE, ref zAlloc );
            }
            if ( pzBuffer != null )
            {
              pzBuffer = zAlloc;
            }
          }
          else
          {
            pNew.flags2 = 0;
            if ( !ExprHasAnyProperty( p, EP_TokenOnly ) )
            {
              pNew.pLeft = sqlite3ExprDup( db, p.pLeft, 0 );
              pNew.pRight = sqlite3ExprDup( db, p.pRight, 0 );
            }
          }
        }
      }
      return pNew;
    }